path use用法 - 我如何獲得正在執行的Perl腳本的完整路徑?




perl模組 @inc (17)

__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;

請添加任何建議。

我有Perl腳本,需要在執行過程中確定腳本的完整路徑和文件名。 我發現取決於你如何調用腳本$0變化,有時包含fullpath+filename ,有時只是filename 。 因為工作目錄可能會有所不同,所以我想不出一種可靠地獲取腳本的fullpath+filename的方法。

任何人都有解決方案?


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 

#!/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


一些簡短的背景:

不幸的是,Unix API並沒有提供一個正在運行的程序和可執行文件的完整路徑。 事實上,執行你的程序可以在該領域提供任何想要的東西,通常會告訴程序它是什麼。 正如所有答案指出的那樣,有各種啟發式方法來尋找可能的候選人。 但是,搜索整個文件系統的任何工作都不會總是有效,甚至如果可執行文件被移動或刪除,那也將失敗。

但是你不希望Perl的可執行文件,這是實際運行的,而是它正在執行的腳本。 Perl需要知道腳本在哪裡找到它。 它存儲在__FILE__ ,而$0來自Unix API。 這仍然可以是一個相對路徑,所以請參考Mark的建議並使用File::Spec->rel2abs( __FILE__ );對其進行標記File::Spec->rel2abs( __FILE__ );


沒有任何外部模塊,對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

有幾種方法:

  • $0是POSIX提供的當前正在執行的腳本,相對於當前工作目錄(如果腳本處於或低於CWD)
  • 此外, cwd()getcwd()abs_path()Cwd模塊提供,並告訴您腳本從哪裡運行
  • 模塊FindBin提供$Bin$RealBin變量, $RealBin變量通常是執行腳本的路徑; 該模塊還提供$Script的名稱$Script$RealScript
  • __FILE__是Perl解釋器在編譯期間處理的實際文件,包括其完整路徑。

我已經看到前三個( $0Cwd模塊和FindBin模塊)在mod_perl下失敗,產生無價值的輸出,例如'.' 或者一個空字符串。 在這樣的環境中,我使用__FILE__並使用File::Basename模塊獲取路徑:

use File::Basename;
my $dirname = 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/;

你在找這個嗎?:

my $thisfile = $1 if $0 =~
/\\([^\\]*)$|\/([^\/]*)$/;

print "You are running $thisfile
now.\n";

輸出將如下所示:

You are running MyFileName.pl now.

它適用於Windows和Unix。


$ 0通常是您程序的名稱,那麼如何?

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

在我看來,這應該工作,因為abs_path知道你是否使用相對或絕對路徑。

更新對於任何閱讀這些年後的人,你應該閱讀德魯的答案。 這比我的好多了。


$^X什麼問題?

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

會給你正在使用的Perl二進製文件的完整路徑。

翻轉


為了獲得包含腳本的目錄的路徑,我使用了已經給出的答案的組合。

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

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

使用dirname(__FILE__)的問題在於它不遵循符號鏈接。 我不得不使用這個腳本來跟踪符號鏈接到實際的文件位置。

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

不需要使用外部模塊,只需一行就可以獲得文件名和相對路徑。 如果您正在使用模塊並需要應用相對於腳本目錄的路徑,則相對路徑就足夠了。

$0 =~ m/(.+)[\/\\](.+)$/;
print "full path: $1, file name: $2\n";

perlfaq8使用$0上的rel2abs()函數回答了一個非常類似的問題。 該功能可以在File :: Spec中找到。


在* nix上,您可能有“whereis”命令,它會搜索您的$ PATH以查找具有給定名稱的二進製文件。 如果$ 0不包含完整的路徑名,那麼運行whereis $ scriptname並將結果保存到變量中會告訴您腳本的位置。


我認為你正在尋找的模塊是FindBin:

#!/usr/bin/perl
use FindBin;

$0 = "stealth";
print "The actual path to this is: $FindBin::Bin/$FindBin::Script\n";







perl path location