如何获得正在执行的Perl脚本的完整路径?
我有Perl脚本,需要在执行期间确定脚本的完整路径和文件名。我发现,取决于脚本的调用方式," $ 0"有所不同,有时包含" fullpath + filename",有时仅包含" filename"。因为工作目录也可能变化,所以我想不出一种可靠地获取脚本的" fullpath + filename"的方法。
任何人都有解决方案吗?
解决方案
回答
在* nix上,我们可能具有" whereis"命令,该命令在$ PATH中搜索具有给定名称的二进制文件。如果$ 0不包含完整路径名,则运行whereis $ scriptname并将结果保存到变量中应该会告诉我们脚本的位置。
回答
$ 0通常是程序的名称,那么这又如何呢?
use Cwd 'abs_path'; print abs_path($ENV{'SCRIPT_NAME'});
在我看来,这应该作为abs_path知道我们正在使用相对还是绝对路径。
更新对于多年后阅读本手册的任何人,我们都应该阅读以下Drew的答案。比我的好多了。
回答
你有没有尝试过:
use FindBin '$Bin'; print "The script is located in $Bin.\n";
或者
#!/usr/bin/perl use FindBin;use Cwd qw(abs_path); my $path = abs_path(= "stealth"; print "The actual path to this is: $FindBin::Bin/$FindBin::Script\n";Use File::Spec; File::Spec->rel2abs( __FILE__ );); print "$path\n";
这实际上取决于它的调用方式以及它是CGI还是从常规Shell运行等。
回答
我认为我们要查找的模块是FindBin:
use File::Basename; my $dirname = dirname(__FILE__);
回答
我们可以使用FindBin,Cwd,File :: Basename或者它们的组合。它们都在Perl IIRC的基本发行版中。
我过去使用过Cwd:
Cwd:
##代码##回答
##代码##http://perldoc.perl.org/File/Spec/Unix.html
回答
perlfaq8通过在$ 0上使用rel2abs()函数来回答一个非常类似的问题。该功能可以在File :: Spec中找到。
回答
一些简短的背景:
不幸的是,Unix API没有为正在运行的程序提供可执行文件的完整路径。实际上,执行程序可以在通常告诉我们程序内容的字段中提供所需的内容。正如所有答案所指出的那样,有各种启发式方法可以找到可能的候选人。但是搜索整个文件系统总是可行的,即使移动或者删除了可执行文件,这也将失败。
但是我们不希望Perl可执行文件(实际上正在运行),而是要执行的脚本。而且Perl需要知道脚本在哪里可以找到它。它将其存储在__FILE__中,而$ 0来自Unix API。这仍然可以是相对路径,因此请采纳Mark的建议并使用`File :: Spec-> rel2abs(FILE);将其标准化。
回答
有几种方法:
- $ 0是POSIX提供的当前正在执行的脚本,相对于当前工作目录(如果脚本位于CWD或者以下)
- 另外,
Cwd
模块提供了cwd()
,getcwd()
和'abs_path()`,并告诉我们脚本从何处运行。 - FindBin模块提供$ Bin和$ RealBin变量,它们通常是执行脚本的路径。该模块还提供$$ Script和$ RealScript这两个脚本的名称
- __FILE__是Perl解释器在编译过程中处理的实际文件,包括其完整路径。
我已经看到前三个($ 0,Cwd模块和FindBin模块)在mod_perl下失败,产生了毫无价值的输出,例如'。'或者空字符串。在这样的环境中,我使用__FILE__
并使用File :: Basename
模块获取路径:
回答
我们想要获取到$ 0或者__FILE__的绝对路径。唯一的麻烦是,如果有人执行了" chdir()"并且" $ 0"是相对的,那么我们需要在" BEGIN {}"中获取绝对路径以防止出现任何意外。
FindBin试图更好地在$ PATH中寻找与basename($ 0)相匹配的内容,但是有时候这样做太令人惊讶了(特别是:文件"正确在我们面前"。
为此,File :: Fu具有File :: Fu-> program_name和File :: Fu-> program_dir。