Re: Getting the filename from full path name ?
by davido (Cardinal) on Apr 15, 2004 at 03:12 UTC
|
See File::Basename. It's a core module, if I'm not mistaken, so you don't even have to install it before using it.
use File::Basename;
my $path = '/home/username/public_html/somepath/2004-04-14-0002136';
my $filename = basename($path);
print $filename, "\n";
| [reply] [d/l] |
|
|
Actually File::Basename is to say bluntly a turd. You are much better off using File::Spec and or the functional equivelents in File::Spec::Functions. File::Basename was effectvely deprecated when File::Spec was created (which it was to fix a whole bunch of know problems in the Basename, some outstanding to this day) but it never was marked as such or removed for hysterical porpoises. File::Spec is in the core and it should be used as a general rule for manipulating paths and directories and the like.
Anyway, the File::Spec::Functions way would be:
use File::Spec::Functions qw(splitpath);
my (undef,undef,$file)=splitpath($path);
Or:
use File::Spec;
my ($vol,$path,$file)=File::Spec->splitpath($path);
Also IMO its not worth ignoring the $vol just becuase _your_ OS doesnt have such a concept. If you use File::Spec and assume there will be a volume then everything will work out regardless of where youtr code ends up.
---
demerphq
First they ignore you, then they laugh at you, then they fight you, then you win.
-- Gandhi
| [reply] [d/l] [select] |
|
|
It would be nice if File::Spec had a basename function, too.
E.g. sub basename { (splitpath($_[0]))[-1] }. And probably also dirname.
| [reply] [d/l] |
|
|
|
|
|
|
|
|
|
|
| [reply] |
Re: Getting the filename from full path name ?
by etcshadow (Priest) on Apr 15, 2004 at 03:48 UTC
|
For portability's sake, use the File::Spec or File::Basename module (because different OSs have different rules for what separates the path, and such). However, in answer to the general question of how one does this sort of string manipulation in perl:
my @path_pieces = split('/', $path);
my $last_path_piece = $path_pieces[$#path_pieces];
or
my ($last_path_piece) = $path =~ m|/(.*?)$|;
my ($last_path_piece) = $path =~ m|([^/]*)$|;
to give a couple of the more idiomatic methods.
------------
:Wq
Not an editor command: Wq
| [reply] [d/l] [select] |
|
|
Your second solution matches the first / in the path. As Chris stated above you probably would rather do:
my ($file) = $a =~ m|/([^/]+)$|;
satchm0h
| [reply] [d/l] |
|
|
Yes, sorry. I made the classic mistake of assuming that non-greedy matching was, in fact, non-greedy. In general, I avoid the use of non-greedy matching (instead, being explicit about what I don't want the match to bleed into) for this basic reason. I was just being sloppy.
------------
:Wq
Not an editor command: Wq
| [reply] [d/l] |
Re: Getting the filename from full path name ?
by thor (Priest) on Apr 15, 2004 at 03:38 UTC
|
While File::Basename is the way to go, I thought that your proposed solution was a bit thought provoking. So, I decided to see if I could do it. Here's what I came up with:
$a = "foo/bar/baz";
my $pos = my $save_pos = 0;
do {
$pos = index($a, "/", $pos + 1 );
$save_pos = $pos if $pos != -1;
} while ($pos != -1);
print substr($a, $save_pos + 1);
I'm sure that someone can whittle that down by quite a bit, but it was a fun diversion...:)
| [reply] [d/l] |
|
|
| [reply] |
|
|
m{/([^/]+)$}
(split/\//)[-1]
| [reply] [d/l] [select] |
|
|
my $a = "foo/bar/baz";
my ($file) = $a =~ /\/(.*?)$/;
Update: Thank you Chris, the code should be:
my ($file) = $a =~ m|/([^/]+)$|;
| [reply] [d/l] [select] |
|
|
| [reply] [d/l] |
|
|
my ($file) = $a =~ m|/([^/]+)$|;
Your exp matches starting with the first slash
Chris | [reply] [d/l] |