Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling

Parsing a filename

by rooneyl (Sexton)
on Jul 07, 2008 at 17:34 UTC ( #696049=perlquestion: print w/replies, xml ) Need Help??
rooneyl has asked for the wisdom of the Perl Monks concerning the following question:

Hello, I know this subject has been covered,but I don't seem to get it. I have got a cgi script that uploads a file. I am using File::Basename to split the path to extract just the file name and extension. it works fine with Unix path separators, but I can not get it to work when dealing with a windows path. It strips out the path separators, but doesn't give the filename.
If I upload a file called C:\Documents and Settings\Ryan\My Documents\sample.txt it gives me the full path minus the path separators.
use File::Basename; my ($name, $path, $suffix); my $filename_with_path_unix = "/usr/local/sample.txt"; print "path is "; print $filename_with_path_unix."\n" ; # test 1, unix print "TEST #1\n"; ( $name, $path, $suffix ) = fileparse( $filename_with_path_unix, "\.[^ +.]*" ); print $name."\n"; print $path."\n"; print $suffix."\n"; print "File is ". $name.$suffix."\n"; #test 2, dos print "TEST #2\n"; my $filename_with_path_dos = "C:\Documents and Settings\My Documents\s +ample.txt"; print "path is ".$filename_with_path_dos."\n"; ( $name, $path, $suffix ) = fileparse( $filename_with_path_dos, "/.[^. +]*" ); print $name."\n"; print $path."\n"; print $suffix."\n"; print "File is ". $name.$suffix."\n";

The output for Unix is sample.txt.
The output for windows is C:Documents and SettingsMy Documentssample.txt.
Thank you for any help.

Replies are listed 'Best First'.
Re: Parsing a filename
by toolic (Bishop) on Jul 07, 2008 at 17:45 UTC
    If you used the strictures use strict;use warnings;, you would have seen these warning messages:
    Unrecognized escape \D passed through Unrecognized escape \M passed through Unrecognized escape \s passed through

    Use single quotes to avoid interpolation:

    my $filename_with_path_dos = 'C:\Documents and Settings\My Documents\s +ample.txt';

    This prints:

    path is /usr/local/sample.txt TEST #1 sample /usr/local/ .txt File is sample.txt TEST #2 path is C:\Documents and Settings\My Documents\sample.txt C:\Documents and Settings\My Documents\sample.txt ./ File is C:\Documents and Settings\My Documents\sample.txt
Re: Parsing a filename
by tomfahle (Priest) on Jul 07, 2008 at 17:47 UTC

    It's just a matter of quoting. You've to escpape your backslashes \ (\\) or use single quotes (').

    "C:\\Documents and Settings\\My Documents\\sample.txt";


    'C:\\Documents and Settings\\My Documents\\sample.txt';

    Otherwise it's seen like this


    Hope this helps.

Re: Parsing a filename
by graff (Chancellor) on Jul 08, 2008 at 00:46 UTC
    If you want a single script to use File::Basename on pathname strings that come from different machines, I think you'll need to tell it how to behave for each input string, which means you have to check for backslashes (and this will probably suffice).

    You probably want something like this (I've written it so that it expects you to provide one or more pathname strings as command-line args, and these may need to be quoted in some way, depending on what sort of shell you are usng):

    #!/usr/bin/perl use strict; use File::Basename; for my $pathname ( @ARGV ) { my $ostype = ( $pathname =~ /\\/ ) ? "MSDOS" : "UNIX"; fileparse_set_fstype( $ostype ); warn "\n parsing $pathname using $ostype rules\n"; my ( $name, $path, $suffix ) = fileparse( $pathname, qr{\.\w+$} ); print "Name: $name\nPath: $path\n.Ext: $suffix\n"; }
    Here's a sample run (using a bash shell on a unix box, so single quotes to protect the backslashes from interpretation by the shell):
    $ ./ 'c:\foo\bar\baz.exe' /usr/share/doc/bash/bash.pdf parsing c:\foo\bar\baz.exe using MSDOS rules Name: baz Path: c:\foo\bar\ .Ext: .exe parsing /usr/share/doc/bash/bash.pdf using UNIX rules Name: bash Path: /usr/share/doc/bash/ .Ext: .pdf

    (update: In case it's not obvious, I'm not suggesting that you should use a separate command-line script from within your CGI code. The point of my script is simply to demonstrate the use of the "fileparse_set_fstype()" function in File::Basename, which is what you need in order to tell the fileparse() function how to behave for a given input. Also, I fixed a spelling error in my script's output.)

      Thank you, you have cleared things up for me.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://696049]
Approved by toolic
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others wandering the Monastery: (5)
As of 2018-02-19 18:15 GMT
Find Nodes?
    Voting Booth?
    When it is dark outside I am happiest to see ...

    Results (266 votes). Check out past polls.