Answers:
有几种方法:
$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__);
__FILE__
)不能按预期工作?我最终得到了执行脚本的相对路径,而被接受的答案给出了完整的绝对路径。
dirname(__FILE__)
不会跟随符号链接,因此,如果您链接了可执行文件,并且希望在安装位置中找到其他文件的位置,则需要检查if( -l __FILE__)
,然后单击dirname(readlink(__FILE__))
。
perl -e 'use Module::CoreList; print Module::CoreList->first_release("File::Basename");'; echo
。为此File::Basename
,是90年代末发布的Perl 5.0.0,我认为现在已经可以节省使用。
$ 0通常是程序的名称,那么这又如何呢?
use Cwd 'abs_path';
print abs_path($0);
在我看来,这应该作为abs_path知道您正在使用相对还是绝对路径。
更新对于这几年以后阅读的任何人,您都应该阅读Drew的答案。比我的好多了。
realpath
,那么它是的同义词abs_path
perl -e 'use Cwd "abs_path";print abs_path($0);'
/tmp/-e
-e
)时,我相信perl会创建一个临时文件来存储您的内联脚本。就您而言,位置似乎是/tmp
。您期望结果是什么?
一些简短的背景:
不幸的是,Unix API没有为正在运行的程序提供可执行文件的完整路径。实际上,执行您的程序可以在通常告诉您程序是什么的字段中提供所需的内容。正如所有答案所指出的那样,有各种启发式方法可以找到可能的候选人。但是搜索整个文件系统总是可行的,即使移动或删除了可执行文件,即使这样也会失败。
但是您不希望Perl可执行文件(实际上正在运行),而是要执行的脚本。而且Perl需要知道脚本在哪里可以找到它。它将它存储在中__FILE__
,而$0
来自Unix API。这仍然可以是相对路径,因此请接受Mark的建议并通过File::Spec->rel2abs( __FILE__ );
__FILE__
仍然给了我一条相对的道路。即“。”。
你有没有尝试过:
$ENV{'SCRIPT_NAME'}
要么
use FindBin '$Bin';
print "The script is located in $Bin.\n";
这实际上取决于它的调用方式以及它是CGI还是从常规Shell运行等。
#!/usr/bin/perl -w
use strict;
my $path = $0;
$path =~ s/\.\///g;
if ($path =~ /\//){
if ($path =~ /^\//){
$path =~ /^((\/[^\/]+){1,}\/)[^\/]+$/;
$path = $1;
}
else {
$path =~ /^(([^\/]+\/){1,})[^\/]+$/;
my $path_b = $1;
my $path_a = `pwd`;
chop($path_a);
$path = $path_a."/".$path_b;
}
}
else{
$path = `pwd`;
chop($path);
$path.="/";
}
$path =~ s/\/\//\//g;
print "\n$path\n";
:DD
use strict ; use warnings ; use Cwd 'abs_path';
sub ResolveMyProductBaseDir {
# Start - Resolve the ProductBaseDir
#resolve the run dir where this scripts is placed
my $ScriptAbsolutPath = abs_path($0) ;
#debug print "\$ScriptAbsolutPath is $ScriptAbsolutPath \n" ;
$ScriptAbsolutPath =~ m/^(.*)(\\|\/)(.*)\.([a-z]*)/;
$RunDir = $1 ;
#debug print "\$1 is $1 \n" ;
#change the \'s to /'s if we are on Windows
$RunDir =~s/\\/\//gi ;
my @DirParts = split ('/' , $RunDir) ;
for (my $count=0; $count < 4; $count++) { pop @DirParts ; }
my $ProductBaseDir = join ( '/' , @DirParts ) ;
# Stop - Resolve the ProductBaseDir
#debug print "ResolveMyProductBaseDir $ProductBaseDir is $ProductBaseDir \n" ;
return $ProductBaseDir ;
} #eof sub
问题所在 __FILE__
在于它将打印核心模块“ .pm”路径,而不必打印正在运行的“ .cgi”或“ .pl”脚本路径。我想这取决于您的目标是什么。
在我看来,Cwd
只需要为mod_perl更新即可。这是我的建议:
my $path;
use File::Basename;
my $file = basename($ENV{SCRIPT_NAME});
if (exists $ENV{MOD_PERL} && ($ENV{MOD_PERL_API_VERSION} < 2)) {
if ($^O =~/Win/) {
$path = `echo %cd%`;
chop $path;
$path =~ s!\\!/!g;
$path .= $ENV{SCRIPT_NAME};
}
else {
$path = `pwd`;
$path .= "/$file";
}
# add support for other operating systems
}
else {
require Cwd;
$path = Cwd::getcwd()."/$file";
}
print $path;
请添加任何建议。
没有任何对shell有效的外部模块,即使使用'../'也可以很好地工作:
my $self = `pwd`;
chomp $self;
$self .='/'.$1 if $0 =~/([^\/]*)$/; #keep the filename only
print "self=$self\n";
测试:
$ /my/temp/Host$ perl ./host-mod.pl
self=/my/temp/Host/host-mod.pl
$ /my/temp/Host$ ./host-mod.pl
self=/my/temp/Host/host-mod.pl
$ /my/temp/Host$ ../Host/./host-mod.pl
self=/my/temp/Host/host-mod.pl
实际上,所有无库解决方案都无法通过多种方式来编写路径(请考虑../或/bla/x/../bin/./x/../等。我的解决方案看起来像我有一个怪癖:我不知道为什么我必须两次运行替换项,否则我会得到一个虚假的“ ./”或“ ../”。对我来说似乎很健壮。
my $callpath = $0;
my $pwd = `pwd`; chomp($pwd);
# if called relative -> add pwd in front
if ($callpath !~ /^\//) { $callpath = $pwd."/".$callpath; }
# do the cleanup
$callpath =~ s!^\./!!; # starts with ./ -> drop
$callpath =~ s!/\./!/!g; # /./ -> /
$callpath =~ s!/\./!/!g; # /./ -> / (twice)
$callpath =~ s!/[^/]+/\.\./!/!g; # /xxx/../ -> /
$callpath =~ s!/[^/]+/\.\./!/!g; # /xxx/../ -> / (twice)
my $calldir = $callpath;
$calldir =~ s/(.*)\/([^\/]+)/$1/;
“最佳”答案都不适合我。使用FindBin'$ Bin'或Cwd的问题是它们返回所有符号链接已解析的绝对路径。在我的情况下,我需要带有符号链接的确切路径-与返回Unix命令“ pwd”相同,而不是“ pwd -P”。以下功能提供了解决方案:
sub get_script_full_path {
use File::Basename;
use File::Spec;
use Cwd qw(chdir cwd);
my $curr_dir = cwd();
chdir(dirname($0));
my $dir = $ENV{PWD};
chdir( $curr_dir);
return File::Spec->catfile($dir, basename($0));
}
在Windows上,使用dirname
和abs_path
一起最适合我。
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";
原因如下:
# 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";
这有什么错$^X
?
#!/usr/bin/env perl<br>
print "This is executed by $^X\n";
将为您提供所用Perl二进制文件的完整路径。
翻转
在* nix上,您可能具有“ whereis”命令,该命令在$ PATH中搜索具有给定名称的二进制文件。如果$ 0不包含完整路径名,则运行whereis $ scriptname并将结果保存到变量中将告诉您脚本的位置。