I have Perl script and need to determine the full path and filename of the script during execution. I discovered that depending on how you call the script $0
va
Getting the absolute path to $0
or __FILE__
is what you want. The only trouble is if someone did a chdir()
and the $0
was relative -- then you need to get the absolute path in a BEGIN{}
to prevent any surprises.
FindBin
tries to go one better and grovel around in the $PATH
for something matching the basename($0)
, but there are times when that does far-too-surprising things (specifically: when the file is "right in front of you" in the cwd.)
File::Fu
has File::Fu->program_name
and File::Fu->program_dir
for this.
There are a few ways:
cwd()
, getcwd()
and abs_path()
are provided by the Cwd module and tell you where the script is being run from$Bin
& $RealBin
variables that usually are the path to the executing script; this module also provides $Script
& $RealScript
that are the name of the scriptI've seen the first three ($0, the Cwd module and the FindBin module) fail under mod_perl
spectacularly, producing worthless output such as '.'
or an empty string. In such environments, I use __FILE__ and get the path from that using the File::Basename module:
use File::Basename;
my $dirname = dirname(__FILE__);
You could use FindBin, Cwd, File::Basename, or a combination of them. They're all in the base distribution of Perl IIRC.
I used Cwd in the past:
Cwd:
use Cwd qw(abs_path);
my $path = abs_path($0);
print "$path\n";
On Windows using dirname
and abs_path
together worked best for me.
use File::Basename;
use Cwd qw(abs_path);
# absolute path of the directory containing the executing script
my $abs_dirname = dirname(abs_path($0));
print "\ndirname(abs_path(\$0)) -> $abs_dirname\n";
here's why:
# this gives the answer I want in relative path form, not absolute
my $rel_dirname = dirname(__FILE__);
print "dirname(__FILE__) -> $rel_dirname\n";
# this gives the slightly wrong answer, but in the form I want
my $full_filepath = abs_path($0);
print "abs_path(\$0) -> $full_filepath\n";
$0 is typically the name of your program, so how about this?
use Cwd 'abs_path';
print abs_path($0);
Seems to me that this should work as abs_path knows if you are using a relative or absolute path.
Update For anyone reading this years later, you should read Drew's answer. It's much better than mine.
The problem with just using dirname(__FILE__)
is that it doesn't follow symlinks. I had to use this for my script to follow the symlink to the actual file location.
use File::Basename;
my $script_dir = undef;
if(-l __FILE__) {
$script_dir = dirname(readlink(__FILE__));
}
else {
$script_dir = dirname(__FILE__);
}