Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Paths in Perl

by tachyon (Chancellor)
on Sep 04, 2001 at 17:43 UTC ( [id://110030]=perltutorial: print w/replies, xml ) Need Help??

Different Operating Systems use different characters as their path separator when specifying directory and file paths:

foo/bar/baz    # *nix uses a /
foo\bar\baz    # Win32 uses a \
foo:bar:baz    # Mac OS 9 uses a :
foo/bar/baz    # Mac OS X uses a / (usually!)

In Perl you can generally just use a / as your path separator (except on Mac OS 9, thanks Hanamaki). Why? Because Perl will automagically convert the / to the correct path separator for the system it is running on! This means that coding Windows paths like this

$path = "\\foo\\bar\\baz";

is not required. You can just use this:

$path = "/foo/bar/baz";

and things will be fine. In fact using \\ can be problematic, but you probably already know that :-)

If you want to display the expected system delimiter to a user (ie hide the fact that you are using / internally) you can just do something like this:

my $perl_path = '/foo/bar/baz'; (my $win_path = $perl_path) =~ tr!/!\\!; print "Perl still sees: $perl_path\n"; print "But we can print: $win_path\n";

If you need to do lots of conversions just write a sub like this:

my $perl_path = '/foo/bar/baz'; print "This is the Windows path: ", win_path($perl_path), "\n"; sub win_path { (my $path = shift) =~ tr!/!\\!; return $path; }
So there you have it. Paths in Perl. By using a / you make it much easier to port your code to another system. For truly portable methods look into the File::Spec module (part of the standard distro) and perlman:perlport. Thanks to wog and Hanamaki for this suggestion. And if you have been converting / to \\ ....

Replies are listed 'Best First'.
Re: Paths in Perl
by Hanamaki (Chaplain) on Sep 04, 2001 at 18:36 UTC
    In Perl you can just use a  /as your path separator. Why? Because Perl with automagically convert the /to the correct path separator for the system it is running on!

    Unfortunately this is not true for Perl on (classic) MacOS. On MacOS you can use / for manipulating @INC but not for other file pathes.
    File::Spec which currently undergoes a major rewrite to handle MacPerl and VMS in a better way is for sure the way to go.
    See also perlport

    Hanamaki
Re: Paths in Perl
by Anonymous Monk on Sep 04, 2001 at 19:05 UTC

    I have always found paths and chdir to be somewhat of a pain in Perl. So as he does not seem to be hangin around anymore here is a excellent snippet from Abigail that gives you scoped chdir.

    package Chdir; sub TIESCALAR {my $class = shift; bless \$class => $class} sub STORE {${$_ [0]} = $_ [1]; chdir $_ [1]} sub FETCH {${$_ [0]}}

    This allows you to have scoped chdir, ie if you do a local $dir= 'newdir' in a block, then the directory changes back to it's initial value at the end of the block:

    package main; use vars qw /$dir/; tie $dir => 'Chdir'; $dir = '/tmp'; print "Dir = " . `pwd`; { local $dir = '/etc'; print "Dir = " . `pwd`; } print "Dir = " . `pwd`;

    mirod for Abigail


      Michael Schwern cpanned a similar module just today. Synchronicity?

      Update: I looked at the module code before I posted this node and it seemed to be using the same methodology as shown above. It appears that the module was developed from the same snippet that Abigail posted to P5P. Thanks to mirod for pointing this out and for posting the code. Further kudos for posting it anonymously.

      John.
      --

Re: Paths in Perl
by John M. Dlugosz (Monsignor) on Sep 05, 2001 at 02:35 UTC

    The Opposing View

    Using '/' for paths in Perl gives almost no problems on DOS and Windows machines, because the underlying OS accepts / as a synonym for \ (most of the time).

    But is that true for all OS's and platforms? Like someone already said, it doesn't work on the Mac. The Perl interpreter itself might change / to : before calling the OS, but what about real /'s in file names, like "notes from 4/27/99"? What about :'s in the file name?

    A solid program should always use the native path separator and do so uniformly and consistantly.

    If that's not handy, Perl 6 will reportetly offer uniform URL support, so you can use file:// notation on files on any OS, with %xx for funny chars and / for seperators. There might also be a module that deals with paths as a collection of nodes and abstracts the actual syntax.

    And just because the OS takes / as an alias, or Perl translates for you behind the scenes, what happens to individual programs you invoke? In the COMMAND.COM shell, the / will parse wrong, as we saw on a recient posting. A program might get confused if / and \ are mixed in the same string. Who knows? you're at the mercy of whoever wrote that program!

    —John

CGI Re: Paths in Perl
by andye (Curate) on Sep 05, 2001 at 17:51 UTC
    'course, there's a different issue if you're writing a CGI script which accepts a file upload.

    Assuming you want to extract the filename from the pathname, I've been known to use something along the lines of this:

    my ($filename) = ($pathname =~ m|[/\\:]([^/\\:]+)$|);
    but if anyone has a better solution then I'd be interested to hear it.

    andy.

      In the CGI::Upload module, the following code was used to parse the full pathname of the uploaded file - This code makes use of HTTP::BrowserDetect to detect the client operating system from the sent HTTP headers and set the parse behaviour of File::Basename accordingly.

      The pertinent code in question ...

      use CGI; use File::Basename; use HTTP::BrowserDetect; sub _handle_file { my ($self, $param) = @_; my $cgi = $self->query; # Determine and set the appropriate file system parsing routines + for the # uploaded path name based upon the HTTP client header informati +on. fileparse_set_fstype( sub { my $browser = HTTP::BrowserDetect->new; return 'MSWin32' if $browser->windows; return 'MacOS' if $browser->mac; $^O; } ); my @file = fileparse( $cgi->param($param), '\.[^\.]*' ); # Return an undefined value if the file name cannot be parsed fr +om the # file field form parameter. return undef unless $file[0]; . . . }

       

      perl -e 'print+unpack("N",pack("B32","00000000000000000000000111100010")),"\n"'

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perltutorial [id://110030]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others avoiding work at the Monastery: (4)
As of 2024-03-29 06:47 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found