more useful options PerlMonks

### 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"; [download] The output for Unix is sample.txt. The output for windows is C:Documents and SettingsMy Documentssample.txt. Thank you for any help. Comment on Parsing a filename Download Code Re: Parsing a filename by toolic (Chancellor) 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 [download] Use single quotes to avoid interpolation: my$filename_with_path_dos = 'C:\Documents and Settings\My Documents\s
+ample.txt';
[download]

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
[download]
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";
[download]

or

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

Otherwise it's seen like this

\D...\M...\s....
[download]

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";
}
[download]
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):
\$ ./test.pl  '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

[download]

(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.

Create A New User
Node Status?
node history
Node Type: perlquestion [id://696049]
Approved by toolic
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others examining the Monastery: (14)
As of 2014-07-29 17:21 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?