실행중인 Perl 스크립트의 전체 경로는 어떻게 얻습니까?
Perl 스크립트가 있으며 실행 중에 스크립트의 전체 경로와 파일 이름을 결정해야합니다. 난 당신이 스크립트를 호출하는 방법에 따라하는 것을 발견 $0
를 포함 때로는 다양하며 fullpath+filename
때로는 단지 filename
. 작업 디렉토리는 다양 할 수 있기 때문에 fullpath+filename
스크립트 를 안정적으로 얻는 방법을 생각할 수 없습니다 .
누구든지 해결책을 얻었습니까?
몇 가지 방법이 있습니다.
$0
스크립트가 CWD 이하인 경우 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__);
$ 0은 일반적으로 프로그램의 이름입니다. 어떻습니까?
use Cwd 'abs_path';
print abs_path($0);
상대 경로 또는 절대 경로를 사용하고 있는지 abs_path가 알고있는 것처럼 작동해야합니다.
업데이트 몇 년 후에 읽은 사람이라면 Drew 's answer를 읽어야 합니다. 내 것보다 훨씬 낫다.
Use File::Spec;
File::Spec->rel2abs( __FILE__ );
http://perldoc.perl.org/File/Spec/Unix.html
찾고있는 모듈이 FindBin이라고 생각합니다.
#!/usr/bin/perl
use FindBin;
$0 = "stealth";
print "The actual path to this is: $FindBin::Bin/$FindBin::Script\n";
당신은 사용할 수 FindBin , CWD , 파일 : 기본 이름 또는 이들의 조합. 그들은 모두 Perl IIRC의 기본 배포판에 있습니다.
나는 과거에 Cwd를 사용했다.
Cwd :
use Cwd qw(abs_path);
my $path = abs_path($0);
print "$path\n";
$0
또는 __FILE__
원하는 경로를 얻는 것입니다. 누군가를 한 경우에만 문제는 chdir()
하고는 $0
당신이에 절대 경로를 얻을 필요가 - 친척 BEGIN{}
어떤 놀라움을 방지 할 수 있습니다.
FindBin
에서 $PATH
일치하는 무언가를 위해 더 잘되고 그루브를 시도 basename($0)
하지만, 너무 놀라운 일을하는 경우가 있습니다 (특히 : 파일이 cwd에서 "바로 앞에 있음").
File::Fu
가 File::Fu->program_name
및 File::Fu->program_dir
이에 대한.
일부 짧은 배경 :
불행히도 Unix API는 실행 파일에 대한 전체 경로를 가진 실행중인 프로그램을 제공하지 않습니다. 실제로, 당신을 실행하는 프로그램은 일반적으로 프로그램이 무엇인지 알려주는 필드에서 원하는 것을 제공 할 수 있습니다. 모든 답변에서 알 수 있듯이, 가능한 후보를 찾기위한 다양한 휴리스틱이 있습니다. 그러나 전체 파일 시스템을 검색하는 데 항상 부족한 것은 없으며 실행 파일을 이동하거나 제거해도 실패합니다.
그러나 실제로 실행중인 Perl 실행 파일은 원하지 않지만 실행중인 스크립트는 원하지 않습니다. 그리고 Perl은 스크립트가 어디에 있는지 알아야합니다. 유닉스 API에서 온 __FILE__
동안 이것을에 저장합니다 $0
. 이것은 여전히 상대 경로 일 수 있으므로 Mark의 제안을 받아이를 표준화하십시오.File::Spec->rel2abs( __FILE__ );
시도해 보셨습니까?
$ENV{'SCRIPT_NAME'}
또는
use FindBin '$Bin';
print "The script is located in $Bin.\n";
실제로 호출되는 방식과 CGI인지 일반 쉘에서 실행 중인지 등에 달려 있습니다.
내 스크립트가 들어있는 디렉토리의 경로를 얻으려면 이미 주어진 답변의 조합을 사용했습니다.
#!/usr/bin/perl
use strict;
use warnings;
use File::Spec;
use File::Basename;
my $dir = dirname(File::Spec->rel2abs(__FILE__));
perlfaq8 은 rel2abs()
on 함수를 사용하여 매우 비슷한 질문에 답변합니다 $0
. 이 기능은 File :: Spec에서 찾을 수 있습니다.
외부 모듈을 사용할 필요가 없으며 한 줄만 사용하면 파일 이름과 상대 경로를 가질 수 있습니다. 모듈을 사용 중이고 스크립트 디렉토리에 상대적인 경로를 적용해야하는 경우 상대 경로로 충분합니다.
$0 =~ m/(.+)[\/\\](.+)$/;
print "full path: $1, file name: $2\n";
#!/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
이것을 찾고 있습니까? :
my $thisfile = $1 if $0 =~
/\\([^\\]*)$|\/([^\/]*)$/;
print "You are running $thisfile
now.\n";
결과는 다음과 같습니다.
You are running MyFileName.pl now.
Windows와 Unix에서 모두 작동합니다.
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;
제안 사항을 추가하십시오.
쉘에 유효한 외부 모듈이 없으면 '../'에서도 잘 작동합니다.
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
The problem with just using dirname(__FILE__)
is that it doesn't follow symlinks. I had to use this for my script to follow the symlink to the actual file location.
use File::Basename;
my $script_dir = undef;
if(-l __FILE__) {
$script_dir = dirname(readlink(__FILE__));
}
else {
$script_dir = dirname(__FILE__);
}
All the library-free solutions don't actually work for more than a few ways to write a path (think ../ or /bla/x/../bin/./x/../ etc. My solution looks like below. I have one quirk: I don't have the faintest idea why I have to run the replacements twice. If I don't, I get a spurious "./" or "../". Apart from that, it seems quite robust to me.
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/;
None of the "top" answers were right for me. The problem with using FindBin '$Bin' or Cwd is that they return absolute path with all symbolic links resolved. In my case I needed the exact path with symbolic links present - the same as returns Unix command "pwd" and not "pwd -P". The following function provides the solution:
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));
}
What's wrong with $^X
?
#!/usr/bin/env perl<br>
print "This is executed by $^X\n";
Would give you the full path to the Perl binary being used.
Evert
On *nix, you likely have the "whereis" command, which searches your $PATH looking for a binary with a given name. If $0 doesn't contain the full path name, running whereis $scriptname and saving the result into a variable should tell you where the script is located.
'Programming' 카테고리의 다른 글
MKMapView라는 클래스를 인스턴스화 할 수 없습니다. (0) | 2020.06.01 |
---|---|
UITableViewCell 사이에 간격을 추가하는 방법 (0) | 2020.06.01 |
UIScrollView를 가져 와서 맨 위로 스크롤 (0) | 2020.06.01 |
BackgroundWorker 및 백그라운드 스레드 (0) | 2020.06.01 |
Google Play 개발자 콘솔에서 앱을 게시 취소하는 방법 (0) | 2020.06.01 |