我有一个Perl脚本,需要在执行期间确定脚本的完整路径和文件名。我发现取决于如何调用脚本,$0
会有所不同,有时包含fullpath+filename
,有时只有filename
。由于工作目录也可能会变化,我想不出一种可靠地获取脚本fullpath+filename
的方法。
有人有解决方案吗?
有几种方法:
$0
是 POSIX 提供的当前执行脚本,如果脚本在当前工作目录下或以下,则相对于当前工作目录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__);
__FILE__
和dirname
)并没有按预期运行?我最终获得了相对于脚本执行位置的路径,而被接受的答案给出了完整的绝对路径。 - Izkatadirname(__FILE__)
不会跟随符号链接,所以如果你链接了可执行文件,并希望找到安装位置中的其他文件的位置,你需要检查 if( -l __FILE__)
,然后使用 dirname(readlink(__FILE__))
。 - DavidGambaperl -e 'use Module::CoreList; print Module::CoreList->first_release("File::Basename");'; echo
。 对于 File::Basename
模块,它是在 Perl 5.0.0 中发布的,该版本发布于90年代末 - 我认为现在使用它是安全的。 - Drew Stephens$0通常是您的程序名称,那么这个怎么样?
use Cwd 'abs_path';
print abs_path($0);
我觉得这应该可行,因为abs_path知道你是使用相对路径还是绝对路径。
更新对于那些几年后读到这篇文章的人,你应该阅读Drew的答案,他的答案比我的好多了。
realpath
是 abs_path
的同义词,如果你更喜欢没有下划线的名称,可以选择使用它。 - vol7ronperl -e 'use Cwd "abs_path";print abs_path($0);'
打印出 /tmp/-e
。 - leonbloy-e
参数在命令行中执行 Perl 脚本时,Perl 会创建一个临时文件以存储您的内联脚本。在您的情况下,它看起来位于 /tmp
目录。您对结果有何期望? - GreenGiantuse File::Spec;
File::Spec->rel2abs( __FILE__ );
我认为你要找的模块是FindBin:
#!/usr/bin/perl
use FindBin;
$0 = "stealth";
print "The actual path to this is: $FindBin::Bin/$FindBin::Script\n";
use Cwd qw(abs_path);
my $path = abs_path($0);
print "$path\n";
$0
或__FILE__
的绝对路径是您想要的。唯一的麻烦是,如果有人做了一个chdir()
,并且$0
是相对的-那么你需要在BEGIN{}
中获取绝对路径以避免任何意外情况。
FindBin
试图更进一步,在$PATH
中寻找与basename($0)
匹配的东西,但有时会做出太出乎意料的事情(特别是:当文件在当前工作目录中时)。
File::Fu
有File::Fu->program_name
和File::Fu->program_dir
来实现此功能。chdir()
吗? - SamB一些简短的背景:
不幸的是,Unix API没有提供运行程序的完整路径。实际上,执行您的程序的程序可以在通常告诉您的程序它是什么的字段中提供任何内容。正如所有答案所指出的那样,有各种启发式方法来查找可能的候选项。但除了搜索整个文件系统外,没有什么方法总是有效的,即使这样做也会失败,如果可执行文件被移动或删除。
但是,您不想要运行的Perl可执行文件,而是要执行的脚本。Perl需要知道脚本的位置才能找到它。它将其存储在__FILE__
中,而$0
来自Unix API。这仍然可能是相对路径,因此采用Mark的建议使用File::Spec->rel2abs(__FILE__);
来规范化它。
__FILE__
仍然给我相对路径,即'.'。 - felwithe您尝试过:
$ENV{'SCRIPT_NAME'}
或者
use FindBin '$Bin';
print "The script is located in $Bin.\n";
这实际上取决于它是如何被调用的,以及它是CGI还是从普通shell中运行。
#!/usr/bin/perl
use strict;
use warnings;
use File::Spec;
use File::Basename;
my $dir = dirname(File::Spec->rel2abs(__FILE__));
不需要使用外部模块,只需一行代码即可获取文件名和相对路径。如果您正在使用模块,并且需要应用相对于脚本目录的路径,则相对路径就足够了。
$0 =~ m/(.+)[\/\\](.+)$/;
print "full path: $1, file name: $2\n";
dir
; $myHome = substr($catalog[3],14); $myHome = &rtrim($myHome); print qq(<$myHome>\n);右侧修剪函数以删除尾随空格
sub rtrim { my $string = shift; $string =~ s/\s+$//; return $string; } 只是想分享一下。 - user1210923