如何获取正在执行的 Perl 脚本的完整路径?
我有 Perl 脚本,需要在执行期间确定脚本的完整路径和文件名。 我发现,根据您调用脚本的方式不同,$0
会有所不同,有时包含完整路径+文件名
,有时仅包含文件名
。 因为工作目录也可能有所不同,所以我想不出一种可靠地获取脚本的完整路径+文件名的方法。
有人有解决办法吗?
I have Perl script and need to determine the full path and filename of the script during execution. I discovered that depending on how you call the script $0
varies and sometimes contains the fullpath+filename
and sometimes just filename
. Because the working directory can vary as well I can't think of a way to reliably get the fullpath+filename
of the script.
Anyone got a solution?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(23)
您在寻找这个吗?:
输出将如下所示:
它适用于 Windows 和 Unix。
Are you looking for this?:
The output will look like this:
It works on both Windows and Unix.
:DD
:DD
在 *nix 上,您可能有“whereis”命令,它会搜索您的 $PATH 查找具有给定名称的二进制文件。 如果 $0 不包含完整路径名,则运行 whereis $scriptname 并将结果保存到变量中应该会告诉您脚本所在的位置。
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.
$0 通常是您的程序的名称,那么这个怎么样?
在我看来,这应该可以工作,因为 abs_path 知道您使用的是相对路径还是绝对路径。
更新对于任何年后阅读此书的人,您应该阅读德鲁的回答。 比我的好多了。
$0 is typically the name of your program, so how about this?
Seems to me that this should work as abs_path knows if you are using a relative or absolute path.
Update For anyone reading this years later, you should read Drew's answer. It's much better than mine.
无需使用外部模块,只需一行即可获得文件名和相对路径。 如果您正在使用模块并且需要应用相对于脚本目录的路径,则相对路径就足够了。
There's no need to use external modules, with just one line you can have the file name and relative path. If you are using modules and need to apply a path relative to the script directory, the relative path is enough.
perlfaq8 使用
rel2abs()
函数回答了一个非常相似的问题在$0
上。 该函数可以在 File::Spec 中找到。perlfaq8 answers a very similar question with using the
rel2abs()
function on$0
. That function can be found in File::Spec.为了获取包含我的脚本的目录的路径,我使用了已经给出的答案的组合。
In order to get the path to the directory containing my script I used a combination of answers given already.
您是否尝试过:
或者
这实际上取决于它的调用方式以及它是 CGI 还是从普通 shell 运行等。
Have you tried:
or
It really depends on how it's being called and if it's CGI or being run from a normal shell, etc.
一些简短的背景知识:
不幸的是,Unix API 不提供正在运行的程序以及可执行文件的完整路径。 事实上,执行您的程序可以在通常告诉您的程序是什么的领域提供它想要的任何内容。 正如所有答案所指出的,有各种启发法来寻找可能的候选人。 但是,除了搜索整个文件系统之外,任何方法都可以正常工作,即使移动或删除了可执行文件,搜索也会失败。
但是您不需要实际运行的 Perl 可执行文件,而是它正在执行的脚本。 Perl 需要知道脚本在哪里才能找到它。 它将其存储在
__FILE__
中,而$0
来自 Unix API。 这仍然可以是相对路径,因此请采纳 Mark 的建议并使用File::Spec->rel2abs( __FILE__ ); 对其进行规范化
Some short background:
Unfortunately the Unix API doesn't provide a running program with the full path to the executable. In fact, the program executing yours can provide whatever it wants in the field that normally tells your program what it is. There are, as all the answers point out, various heuristics for finding likely candidates. But nothing short of searching the entire filesystem will always work, and even that will fail if the executable is moved or removed.
But you don't want the Perl executable, which is what's actually running, but the script it is executing. And Perl needs to know where the script is to find it. It stores this in
__FILE__
, while$0
is from the Unix API. This can still be a relative path, so take Mark's suggestion and canonize it withFile::Spec->rel2abs( __FILE__ );
获取
$0
或__FILE__
的绝对路径就是您想要的。 唯一的麻烦是,如果有人执行了chdir()
并且$0
是相对的 - 那么您需要在BEGIN{} 以防止出现任何意外。
FindBin
试图做得更好,并在$PATH
中寻找与basename($0)
匹配的内容,但有时会出现这种情况太令人惊讶的事情(具体来说:当文件在 cwd 中“就在您面前”时。)File::Fu
有File::Fu->program_name
File::Fu->program_nameFile::Fu code> 和File::Fu->program_dir
为此。Getting the absolute path to
$0
or__FILE__
is what you want. The only trouble is if someone did achdir()
and the$0
was relative -- then you need to get the absolute path in aBEGIN{}
to prevent any surprises.FindBin
tries to go one better and grovel around in the$PATH
for something matching thebasename($0)
, but there are times when that does far-too-surprising things (specifically: when the file is "right in front of you" in the cwd.)File::Fu
hasFile::Fu->program_name
andFile::Fu->program_dir
for this.您可以使用FindBin,Cwd, File::Basename,或它们的组合。 它们都在 Perl IIRC 的基础发行版中。
我以前用过Cwd:
Cwd:
You could use FindBin, Cwd, File::Basename, or a combination of them. They're all in the base distribution of Perl IIRC.
I used Cwd in the past:
Cwd:
没有任何外部模块,对 shell 有效,即使使用 '../' 也能正常工作:
测试:
Without any external modules, valid for shell, works well even with '../':
test:
__FILE__
的问题是它会打印核心模块“.pm”路径,而不一定是正在运行的“.cgi”或“.pl”脚本路径。 我想这取决于你的目标是什么。在我看来,
Cwd
只需要更新了 mod_perl。 这是我的建议:请添加任何建议。
The problem with
__FILE__
is that it will print the core module ".pm" path not necessarily the ".cgi" or ".pl" script path that is running. I guess it depends on what your goal is.It seems to me that
Cwd
just needs to be updated for mod_perl. Here is my suggestion:Please add any suggestions.
仅使用 dirname(__FILE__) 的问题是它不遵循符号链接。 我必须在我的脚本中使用它来跟踪符号链接到实际文件位置。
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.$^X
有什么问题吗?将为您提供正在使用的 Perl 二进制文件的完整路径。
翻转
What's wrong with
$^X
?Would give you the full path to the Perl binary being used.
Evert
所有无库解决方案实际上都不适用于多种编写路径的方法(想想 ../ 或 /bla/x/../bin/./x/../ 等。我的解决方案看起来像下面我有一个怪癖:我不知道为什么我必须运行替换两次,除此之外,我会得到一个虚假的“./”或“../”。对我来说似乎相当强大。
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.
“最重要”的答案都不适合我。 使用 FindBin '$Bin' 或 Cwd 的问题是它们返回已解析所有符号链接的绝对路径。 就我而言,我需要存在符号链接的确切路径 - 与返回 Unix 命令“pwd”而不是“pwd -P”相同。 以下函数提供了解决方案:
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:
在 Windows 上,同时使用
dirname
和abs_path
对我来说效果最好。原因如下:
On Windows using
dirname
andabs_path
together worked best for me.here's why:
德鲁的回答给了我:
“。”
Drew's answer gave me:
'.'
http://perldoc.perl.org/File/Spec/Unix.html
http://perldoc.perl.org/File/Spec/Unix.html
我认为您正在寻找的模块是 FindBin:
I think the module you're looking for is FindBin:
有几种方法:
$0
是当前正在执行的脚本由 POSIX 提供,如果脚本位于或低于 CWD,则相对于当前工作目录cwd()
、getcwd()
和abs_path()
由Cwd
模块提供,并告诉您在哪里 运行,FindBin
提供$Bin
&$RealBin
变量通常是执行脚本的路径; 该模块还提供了$Script
&$RealScript
是脚本的名称__FILE__< /code>
是 Perl 解释器在编译期间处理的实际文件,包括其完整路径。
我已经看过前三个(
$0
,< a href="http://perldoc.perl.org/Cwd.html" rel="noreferrer">Cwd
模块和FindBin
模块)在mod_perl
下失败,产生毫无价值的输出,例如'。 '
或空字符串。 在这种环境中,我使用__FILE__
并获取使用File::Basename
模块的路径:There are a few ways:
$0
is the currently executing script as provided by POSIX, relative to the current working directory if the script is at or below the CWDcwd()
,getcwd()
andabs_path()
are provided by theCwd
module and tell you where the script is being run fromFindBin
provides the$Bin
&$RealBin
variables that usually are the path to the executing script; this module also provides$Script
&$RealScript
that are the name of the script__FILE__
is the actual file that the Perl interpreter deals with during compilation, including its full path.I've seen the first three (
$0
, theCwd
module and theFindBin
module) fail undermod_perl
spectacularly, producing worthless output such as'.'
or an empty string. In such environments, I use__FILE__
and get the path from that using theFile::Basename
module: