Re: file name parsing to get the original file name
by Abigail-II (Bishop) on Aug 19, 2003 at 11:04 UTC
|
use File::Basename;
The module comes standard with modern versions of Perl.
Abigail | [reply] [d/l] |
A reply falls below the community's threshold of quality. You may see it by logging in. |
Re: file name parsing to get the original file name
by arthas (Hermit) on Aug 19, 2003 at 13:24 UTC
|
As Abigail-II suggested, use File::BaseName. However, if you are parsing HTML form input, beware: the module is not going to work regardless of the operating system of the client. Windows machines put backslashes (\) instead of slashes (/) for instance, so if you need to receive file uploaded by a Windows client and your program is on an Unix server, you'll need to do:
fileparse_set_fstype("MSWin32");
before calling the parsing function. The default FS type of the module depends on the operaing system where the script runs (it's decided upon examining the $^O variabile).
Michele. | [reply] [d/l] |
|
use File::Basename qw(basename dirname);
print basename("c:\\path\\file.txt"), $/;
print basename("c:/path/file.txt"), $/;
print dirname("c:\\path\\file.txt"), $/;
print dirname("c:/path/file.txt"), $/;
__OUTPUT__
file.txt
file.txt
c:\path
c:/path
"Be lenient in what you accept, strict in what you produce."
-- [ e d @ h a l l e y . c c ] | [reply] [d/l] |
|
Output on a Linux box is...
c:\path\file.txt
file.txt
.
c:/path
...which is obviously wrong if you need to deal with the win32 input. | [reply] |
|
Hi Michele, I was trying your solution since my parsing is indeed HTML form input.Tried the other solutions but can't work, it still does not recognize the '\'
Is there anything that I should need to add before inserting the : fileparse_set_fstype("MSWin32"); Because my html shows an error when I add that line.
Thanks
| [reply] |
|
| [reply] |
Re: file name parsing to get the original file name
by bear0053 (Hermit) on Aug 19, 2003 at 13:55 UTC
|
you can also do the following (maybe a little less efficient way but at least you won't need to require another module)
my $filename = 'xxx/yyy/zzz.a';
my ($tmp1,$tmp2,$name) = split(/\//,$filename);
print "$name";
$name from above will now contain zzz.a | [reply] [d/l] |
|
That's not very flexible. I can understand not needing
to care about separators from different platforms, but
your approach only works if you have two directories and
then the file. It will fail if there's just one directory,
or three.
my $filename = "one/two/three/four/five/six.a";
my $name = (split m{/} => $filename) [-1];
Abigail | [reply] [d/l] |
|
If we are trying for 'best UNIX-only solution that requires no modules', I vote for:
my($name) = $path =~ /([^\/]+)\z/;
I second Abigail-II's suggestion that a module is used, though, as these sorts of problems are generic in nature, and it is very scary to see hundreds of different solutions to the same problem, each with their own independent set of failings.
At least if a single module is used by everybody, then the code is being excercised in a higher percentage of the possible contexts, and problems will be fixed sooner, rather than being discovered much later.
UPDATE: Optimizing the above expression, we can see the speed improve by a factor of 6:
$path =~ /(?:.*\/)?(.+)/s; my $name = $1;
It seems that the Perl regular expression engine does a poor job of dealing with matching a pattern at the end of a string. This is not surprising given that most regular expression engines start searching from the beginning of the string.
| [reply] [d/l] [select] |
|
|
|
|
|
|