如何获取正在执行的Perl脚本的完整路径?

Chr*_*den 164 perl location path

我有Perl脚本,需要在执行期间确定脚本的完整路径和文件名.我发现,根据你调用脚本的方式$0不同而有时包含fullpath+filename,有时只是filename.因为工作目录也可以变化,所以我想不出可靠地获取fullpath+filename脚本的方法.

有人有解决方案吗?

Dre*_*ens 241

有几种方法:

  • $0 是当前正在执行的脚本,由POSIX提供,相对于当前工作目录,如果脚本位于CWD或其下方
  • 此外,cwd(),getcwd()abs_path()通过所提供的Cwd模块,并告诉你的脚本是从运行
  • 该模块FindBin提供的$Bin&$RealBin变量通常是执行脚本的路径; 该模块还提供$Script$RealScript那些脚本的名称
  • __FILE__ 是Perl解释器在编译期间处理的实际文件,包括其完整路径.

我已经看到的前三个($0,该Cwd模块和FindBin模块)下失效mod_perl壮观,产生毫无价值输出诸如'.'或空字符串.在这样的环境中,我使用__FILE__并使用File::Basename模块从中获取路径:

use File::Basename;
my $dirname = dirname(__FILE__);
Run Code Online (Sandbox Code Playgroud)

  • `dirname(__ FILE __)`不遵循符号链接,所以如果链接可执行文件和希望在安装位置找到其他文件的位置,你需要检查`if(-l __FILE __)`然后``dirname (的readlink(__ FILE __))`. (10认同)
  • 看起来abs_path需要与_____FILE_____一起使用,因为它可能只包含路径的名称. (8认同)
  • @vicTROLLA可能是因为这个答案的最大建议(使用带有`__FILE__`的dirname)并不像预期的那样有效?我最终得到了脚本执行的相对路径,而接受的答案给了我完整的绝对路径. (5认同)
  • @IliaRostovtsev您可以在标准模块中首次使用此咒语找到模块:`perl -e'使用Module :: CoreList; print Module :: CoreList-> first_release("File :: Basename");'; echo`.对于在90年代末发布的Perl 5.0.0的`File :: Basename`,我认为现在可以使用了. (3认同)
  • 这确实是最好的解决方案,特别是如果你已经修改了$ 0 (2认同)
  • 所以这对我有用,将它们与@Aftershock(谢谢)放在一起来回答原来的问题。`使用 Cwd 'abs_path'; 使用文件::基本名称;我的$开始;if ( -l __FILE__ ) { $start=目录名(readlink(__FILE__)); } else { $start=dirname(__FILE__); 我的 $fullpath = abs_path($start).'/'; 我的 $filename= 基本名称($start); 打印“$完整路径$文件名”;` (2认同)

Ovi*_*vid 144

$ 0通常是您的程序的名称,那么这个怎么样?

use Cwd 'abs_path';
print abs_path($0);
Run Code Online (Sandbox Code Playgroud)

在我看来这应该工作,因为abs_path知道你是使用相对路径还是绝对路径.

更新对于今年阅读的任何人,您应该阅读下面的Drew的答案.它比我好多了.

  • 关于windows $ 0上的activestate perl的小注释通常包含反斜杠和abs_path返回的正斜杠,所以快速"tr /\// \\ /;" 需要修理它. (11认同)
  • 想补充说有一个`realpath`,它是`abs_path`的同义词,如果你更喜欢无下划线的名字 (3认同)
  • @leonbloy当您执行内联脚本(使用`-e`)时,我相信perl会创建一个临时文件来存储您的内联脚本.在您的情况下,看起来位置是`/ tmp`.您对结果的期望是什么? (2认同)

bmd*_*cks 16

我认为您正在寻找的模块是FindBin:

#!/usr/bin/perl
use FindBin;

$0 = "stealth";
print "The actual path to this is: $FindBin::Bin/$FindBin::Script\n";
Run Code Online (Sandbox Code Playgroud)


Ben*_*ith 11

您可以使用FindBin,Cwd,File :: Basename或它们的组合.它们都在Perl IIRC的基础版本中.

我过去使用过Cwd:

CWD:

use Cwd qw(abs_path);
my $path = abs_path($0);
print "$path\n";
Run Code Online (Sandbox Code Playgroud)

  • 这是不正确的,因为脚本运行时可以更改$ 0. (3认同)

小智 9

获得绝对的路径$0或者__FILE__是你想要的.唯一的麻烦是如果某人做了a chdir()而且$0是亲戚 - 那么你需要获得绝对路径BEGIN{}以防止任何意外.

FindBin尝试更好地去做一个$PATH与之相匹配的东西basename($0),但有时会做出太令人惊讶的事情(特别是:当cwd中的文件"在你面前"时.)

File::FuFile::Fu->program_nameFile::Fu->program_dir此.


wno*_*ise 7

一些简短的背景:

不幸的是,Unix API没有提供带有可执行文件完整路径的正在运行的程序.事实上,执行你的程序可以在字段中提供它想要的任何东西,通常告诉你的程序它是什么.正如所有答案所指出的那样,有各种启发式方法可以找到可能的候选人.但是,搜索整个文件系统总是有效,即使移动或删除可执行文件,也会失败.

但是你不需要Perl可执行文件,它是实际运行的,但是它正在执行的脚本.Perl需要知道脚本在哪里找到它.它存储这__FILE__,而$0从Unix的API.这仍然是一个相对路径,所以采取马克的建议并将其封装File::Spec->rel2abs( __FILE__ );


Sea*_*ean 6

你有没有尝试过:

$ENV{'SCRIPT_NAME'}
Run Code Online (Sandbox Code Playgroud)

要么

use FindBin '$Bin';
print "The script is located in $Bin.\n";
Run Code Online (Sandbox Code Playgroud)

这实际上取决于它是如何被调用的,如果它是CGI还是从普通的shell运行,等等.


小智 6

为了获得包含我脚本的目录的路径,我使用了已经给出的答案组合.

#!/usr/bin/perl
use strict;
use warnings;
use File::Spec;
use File::Basename;

my $dir = dirname(File::Spec->rel2abs(__FILE__));
Run Code Online (Sandbox Code Playgroud)