문제

나는 Perl 스크립트를 확인해야의 전체 경로와 파일이름 스크립트의 동안 실행됩니다.발견하는 방법에 따라 전화 스크립트 $0 까지 다양하며 때때로 포함 fullpath+filename 때로는 그냥 filename.기 때문에 작업 디렉터리를 달라질 수 있습뿐만 아니라 생각할 수 없는 방법을 안정적으로 얻 fullpath+filename 의 스크립트입니다.

누군가 있어 솔루션인가?

도움이 되었습니까?

해결책

몇 가지 방법이 있다:

  • $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__);

다른 팁

$0 은 일반적으로 이름을 그래서 당신의 프로그램의는 방법에 대해 이?

use Cwd 'abs_path';
print abs_path($0);

보기에는 이로 작동해야 합니다 abs_path 을 알고 사용하는 경우에는 상대 또는 절대적인 경로입니다.

업데이트 누구나 읽고 이년 후에 읽어야 합니다린 그의 대답이다.그것은 훨씬 더 좋습니다.

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, 파일::Basename, 또는 그들의 조합.그들은 모두에 기본 배포본의 펄 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::FuFile::Fu->program_nameFile::Fu->program_dir 니다.

몇 가지 짧은 배경:

불행하게도 Unix API 제공하지 않는 실행중인 프로그램의 전체 경로를 실행 파일을 실행합니다.사실,프로그램을 실행하는 당신을 제공할 수 있습 무엇이든 그것이 원하는 분야에서는 일반적으로 알리는 프로그램입니다.가 있으로 모든 대답을 지적 다양한 추론을 찾기 위한 가능성이 후보자.하지만 아무것도 단색의 전체 파일시스템상 작업,그리고 심지어는 것이 실패하는 경우 실행파일이 이동하거나 제거합니다.

하지만 당신이 원하지 않는 Perl 실행되는,실제로 실행되지만,그것은 스크립트 실행됩니다.와 Perl 위치를 알고 있어야 합 스크립트는 그것을 찾을 수 있습니다.그것은 매장에서 이것을 __FILE__, 동 $0 에서 유닉스 API 를 사용합니다.이는 아직도 상대적인 경로를,그래서 마크의 제안과 canonize 로 File::Spec->rel2abs( __FILE__ );

을 시도했다:

$ENV{'SCRIPT_NAME'}

use FindBin '$Bin';
print "The script is located in $Bin.\n";

그것은 정말에 따라 어떻게 호출되는 경우 CGI 또는에서 실행 되는 일반적인 쉘,etc.

을 얻기 위해서는 디렉토리의 경로를 포함하는 스크립트가 조합을 사용의 답변을 주어집니다.

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

my $dir = dirname(File::Spec->rel2abs(__FILE__));

perlfaq8 답변 아주 비슷한 질문을 함께 사용하여 rel2abs() 기능 $0.는 기능을 찾을 수 있습에서 파일::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.

그것은 작품 모두에 윈도우와 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__ 는 그것을 인쇄할 것이 핵심 모듈".이 경로를"반드시".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

문제는 단지 사용 dirname(__FILE__) 는 그것을 따르지 않는 심볼릭 링크.를 사용했다는 이에 대한 스크립트를 따라 심볼릭 링크하는 실제 파일의 위치에 있습니다.

use File::Basename;
my $script_dir = undef;
if(-l __FILE__) {
  $script_dir = dirname(readlink(__FILE__));
}
else {
  $script_dir = dirname(__FILE__);
}

모든 라이브러리-무료 솔루션은 실제로 작동하지 않 이상을 위해 몇 가지 방법을 쓰는 경로(르게 액세스할 수 있습니다.*/또는/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/;

None of the"top"대답이 옳았습니다.문제를 사용하여 FindBin'$Bin'또는 Cwd 은 그들이 반환 절대 경로로 모든 심볼릭 링크를 해결합니다.내 경우에 필요한 정확한 경로로 심볼릭 링크는 현재와 같은 반환 Unix 명령"password"and not"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));
}

무엇을 잘못 $^X ?

#!/usr/bin/env perl<br>
print "This is executed by $^X\n";

를 제공할 것입의 전체 경로를 Perl 바이너리 사용되고 있습니다.

Evert

에*nix,당신은 가능성이 있"whereis"명령으로 검색하$경로를 찾는 이진로 주어진 이름입니다.는 경우$0 이 포함되어 있지 않은 전체 경로 이름은,실행 whereis$scriptname 및 저장 결과 변수로 말해야 스크립트가 있다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top