如果我在某个库代码中,如何确定当前执行的代码文件的路径?我知道通过查看ARGV
可以获取顶层 Perl 文件的路径,但是如果我加载一个库,那么这个库怎样知道它所在的路径呢?
如果我在某个库代码中,如何确定当前执行的代码文件的路径?我知道通过查看ARGV
可以获取顶层 Perl 文件的路径,但是如果我加载一个库,那么这个库怎样知道它所在的路径呢?
__FILE__
token可以给你包括文件名在内的完整路径。你可以使用File::Spec来将其分解成组件:
my ($volume, $directory, $file) = File::Spec->splitpath(__FILE__);
使用FindBin是找到当前可执行文件的文件名最简便的方法:
use FindBin;
use File::Spec;
print "the directory of my script is: " . $FindBin::Bin . "\n";
print "the base name of my script is: " . $FindBin::Script . "\n";
print "the canonical location of my script is: " . File::Spec->catfile($FindBin::Bin, $FindBin::Script) . "\n";
可以通过查看$0
(在命令行调用时脚本的名称)和__FILE__
(当前执行文件的名称)来获取部分信息。
要提取当前执行模块的文件名,请从检查__PACKAGE__
开始,进行一些替换操作后查找%INC
中的文件名。详见perldoc perlvar。
(my $filename = __PACKAGE__ ) =~ s#::#/#g;
$filename .= '.pm';
my $abs_filename = $INC{$filename};
我在我的初始化库中这样做,以便在相对于当前模块的路径中找到配置脚本(我安装了几个代码分支,并且每个分支都有略微不同的配置):
# use the location of the current module as a guide for where to find configs
(my $filename = __PACKAGE__ ) =~ s#::#/#g;
$filename .= '.pm';
(my $path = $INC{$filename}) =~ s#/\Q$filename\E$##g; # strip / and filename
my $abs_config_file = File::Spec->catfile($path, $config_file);
MyApp->initialize($abs_config_file);
__FILE__
和使用%INC
的解决方案。有没有避免使用更简单的__FILE__
变量,而改用%INC
解决方案的原因? - Patrick Böker通过use
或require
引入的任何库都会在特殊的%INC
哈希表中产生一个条目(参见perlvar)。
例如:
use strict;
use warnings;
use Data::Dumper;
print Dumper \%INC;
这将会产生类似以下的输出结果:
$VAR1 = {
'warnings/register.pm' => '/usr/lib/perl5/5.8.8/warnings/register.pm',
'bytes.pm' => '/usr/lib/perl5/5.8.8/bytes.pm',
'XSLoader.pm' => '/usr/lib64/perl5/5.8.8/x86_64-linux-thread-multi/XSLoader.pm',
'Carp.pm' => '/usr/lib/perl5/5.8.8/Carp.pm',
'Exporter.pm' => '/usr/lib/perl5/5.8.8/Exporter.pm',
'strict.pm' => '/usr/lib/perl5/5.8.8/strict.pm',
'warnings.pm' => '/usr/lib/perl5/5.8.8/warnings.pm',
'overload.pm' => '/usr/lib/perl5/5.8.8/overload.pm',
'Data/Dumper.pm' => '/usr/lib64/perl5/5.8.8/x86_64-linux-thread-multi/Data/Dumper.pm'
};
__FILE__
常量,它将返回当前文件名。(另请参见__PACKAGE__
)。use Cwd qw/abs_path/;
my ($real_path) = abs_path($0) =~ m/(.*)myscript.pl/i;
这将实际目录路径放入$real_path中。通常在此之后我还会执行chdir $real_path
,以确保我的代码实际上是从应该的目录中运行的(通常在使用Win32::Daemon编写Windows服务时)。
我导出的abs_path
子例程会给出您提供的任何文件(名称/句柄)的路径。在这种情况下,我提供了$0
,它是正在执行的Perl脚本的名称。
我建议查看Cpan上的Cwd以获取更多指导。
最简单的方法:
print $ENV{'PWD'};
__FILE__
的值应该与%INC
返回的相同。如果您已将相对路径添加到@INC
中,则可能会返回相对文件路径。splitpath()
可以处理此问题,但目录部分将是相对而不是绝对的。如果这是一个问题,您可以使用File::Spec->rel2abs()
将(可能)相对路径转换为绝对路径。 - Michael Carman__FILE__
实际上可能并不是文件。在文件的某个地方输入#line 42 foo.bar
,然后运行warn __FILE__
来尝试一下。 - jrockway__FILE__
可能并不总是返回完整路径,而是返回提供给perl二进制文件的脚本名称。因此,当通过“perl ./myscript.pl”启动时,__FILE__
返回“./myscript.pl”... - Ted