2010-03-08 27 views

回答

16

__FILE__令牌會爲您提供包括文件名的完整路徑。您可以使用File::Spec將其分割成組件:

my ($volume, $directory, $file) = File::Spec->splitpath(__FILE__); 
+0

我認爲這將不能正確處理相對路徑。 – 2010-03-08 17:59:30

+0

@Leon:這取決於你的意思是「正確」。 '__FILE__'的值應該與'%INC'中的值相匹配。如果您已將相對路徑添加到'@ INC',那麼您可能會返回相對路徑。 'splitpath()'會處理那個,但是目錄部分將是相對的,而不是絕對的。如果這是一個問題,你可以使用File :: Spec-> rel2abs()將一個(可能)相對路徑轉換爲絕對路徑。 – 2010-03-08 19:53:12

+0

當然'__FILE__'實際上可能不是文件。嘗試在文件中的某處出現'#line 42 foo.bar'後運行'warn __FILE__'。 – jrockway 2010-03-09 15:33:20

1

的所有庫包括通過userequire產生特殊%INC散列的條目。 (見perlvar)。

例如:

use strict; 
use warnings; 

use Data::Dumper; 

print Dumper \%INC; 

這將產生類似於下面的輸出:

$VAR1 = { 
     'warnings/register.pm' => '/usr/lib/perl5/5.8.8/warnings/register.pm', 
     'bytes.pm' => '/usr/lib/perl5/5.8.8/bytes.pm', 
     'XSLoader.pm' => '/usr/lib64/perl5/5.8.8/x86_64-linux-thread-multi/XSLoader.pm', 
     'Carp.pm' => '/usr/lib/perl5/5.8.8/Carp.pm', 
     'Exporter.pm' => '/usr/lib/perl5/5.8.8/Exporter.pm', 
     'strict.pm' => '/usr/lib/perl5/5.8.8/strict.pm', 
     'warnings.pm' => '/usr/lib/perl5/5.8.8/warnings.pm', 
     'overload.pm' => '/usr/lib/perl5/5.8.8/overload.pm', 
     'Data/Dumper.pm' => '/usr/lib64/perl5/5.8.8/x86_64-linux-thread-multi/Data/Dumper.pm' 
    }; 

此外,還有一個通用__FILE__常數將返回當前的文件名。 (另請參閱__PACKAGE__)。

13

找到文件名當期可執行的最簡單的方法是FindBin

use FindBin; 
use File::Spec; 

print "the directory of my script is: " . $FindBin::Bin . "\n"; 
print "the base name of my script is: " . $FindBin::Script . "\n"; 
print "the canonical location of my script is: " . File::Spec->catfile($FindBin::Bin, $FindBin::Script) . "\n"; 

內部,您可以通過查看$0(腳本的名稱在一些信息得到儘可能調用在命令行)和__FILE__,這是當前正在執行的文件的名稱。 (見perldoc perlvar。)

要提取文件名當前執行的模塊的,開始檢查__PACKAGE__,做一些替代的魔法,然後查找文件名中%INC

(my $filename = __PACKAGE__) =~ s#::#/#g; 
$filename .= '.pm'; 
my $abs_filename = $INC{$filename}; 

我這樣做在我的一個初始化庫中找到相對於當前模塊的路徑中的配置腳本(我有幾個代碼分支並排安裝,每個都有略微不同的配置):

# use the location of the current module as a guide for where to find configs 
(my $filename = __PACKAGE__) =~ s#::#/#g; 
$filename .= '.pm'; 

(my $path = $INC{$filename}) =~ s#/\Q$filename\E$##g; # strip/and filename 
my $abs_config_file = File::Spec->catfile($path, $config_file); 
MyApp->initialize($abs_config_file); 
+0

這將給他的命令行(我認爲)執行腳本的名稱不是正在執行的「庫模塊」的名稱。 – lexu 2010-03-08 17:52:50

+0

@lexu:我在下一段中增加了一點(就在你離開那條評論之後):) – Ether 2010-03-08 17:57:06

+0

對,你的答案很好,但是比_ _ FILE更復雜_ _ – lexu 2010-03-08 21:34:03

1

這是我通常用來獲取執行代碼路徑的代碼片段。

use Cwd qw/abs_path/; 
my ($real_path) = abs_path($0) =~ m/(.*)myscript.pl/i; 

這將實際的目錄路徑放到$ real_path中。在此之後,我通常也會執行chdir $real_path,以確保我的代碼實際上正在處理它應該是的目錄(通常在我使用Win32 :: Daemon編寫Windows服務時)。

我導出的abs_path子例程給出了作爲參數提供的任何文件(名稱/句柄)的路徑。在這種情況下,我提供了$0這是正在執行的Perl腳本的名稱。

我建議在Cpan上檢查Cwd以獲取更多指導。

+0

稍微更通用的寫作方法相同: 使用Cwd qw/abs_path /; (my $ script_path = abs_path($ 0))=〜s | ^(。*)([\/\\])(。*)| $ 1 $ 2 | g; – 2014-08-20 10:03:38

-4

最簡單的方法:

print $ENV{'PWD'}; 
+0

不幸的是,這是行不通的。如果我從/ home/luser執行'/ foo/bar/baz',那麼'$ ENV {PWD}'將返回'/ home/luser /'而不是'/ foo/bar'。 – 2014-06-20 15:16:59

+1

歡迎來到SO。您的答案可能會也可能不會是正確的,但無論哪種方式,我們都會鼓勵人們解釋他們的答案,而不僅僅是發佈代碼片段。 – 2014-06-20 15:48:11

+2

PWD它是bash(也許其他shell)env autoset變量。當某個進程改變目錄並調用你的腳本時,PWD指向前一個目錄,而不是當前目錄。更好地移除這個答案,防止丟失點:) – Znik 2014-10-17 13:29:48

相關問題