回答:
いくつかの方法があります。
$0
スクリプトがCWD以下の場合、現在の作業ディレクトリを基準にした、POSIXによって提供される現在実行中のスクリプトです。cwd()
、getcwd()
およびabs_path()
によって提供されているCwd
モジュールやスクリプトから実行されている場所を教えてくれFindBin
は、通常、実行中のスクリプトへのパスである$Bin
&$RealBin
変数を提供します。このモジュールは、スクリプトの名前である&も提供します$Script
$RealScript
__FILE__
コンパイル中にPerlインタープリターが処理する実際のファイルです(フルパスを含む)。最初の3つ($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
。結果はどうなると思いましたか?
FindBin、Cwd、File :: Basenameを使用できます、またはそれらの組み合わせを。これらはすべて、Perl IIRCの基本ディストリビューションに含まれています。
私は過去にCwdを使用しました:
Cwd:
use Cwd qw(abs_path);
my $path = abs_path($0);
print "$path\n";
への絶対パスを取得する$0
か、それ__FILE__
が必要です。唯一の問題は、誰かがa chdir()
を実行し、$0
が相対だった場合ですBEGIN{}
。驚きを防ぐために、aの絶対パスを取得する必要があります。
FindBin
は、に$PATH
一致するものを1つ上手に探して、でうろうろしますがbasename($0)
、それがあまりにも驚くべきことを行う場合があります(特に、ファイルがcwdの「目の前」にある場合)。
File::Fu
これを持っFile::Fu->program_name
てFile::Fu->program_dir
います。
chdir()
コンパイル時に(永久に)誰もが愚かにする可能性は本当にありますか?
短い背景:
残念ながら、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であるか、通常のシェルから実行されているかなどに本当に依存します。
#!/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__
は、実行中の「.cgi」または「.pl」スクリプトパスではなく、コアモジュールの「.pm」パスを出力することです。それはあなたの目標が何であるかによると思います。
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
ライブラリを使用しないすべてのソリューションは、パスを書き込むためのいくつかの方法(../または/bla/x/../bin/./x/../など)で実際に機能しません。私のソリューションは次のようになります以下に1つの癖があります。なぜ置換を2度実行する必要があるのか、最もわかりにくい考えです。そうしないと、偽の "./"または "../"が表示されます。それ以外に、私にはかなり頑丈に思えます。
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を使用する場合の問題は、すべてのシンボリックリンクが解決された絶対パスを返すことです。私の場合、シンボリックリンクが存在する正確なパスが必要でした-「pwd -P」ではなく、Unixコマンド「pwd」を返すのと同じです。次の関数がソリューションを提供します。
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を実行して結果を変数に保存すると、スクリプトの場所がわかります。