The question
What is the difference between Cwd::cwd
and Cwd::getcwd
in Perl, generally, without regard to any specific platform? Why does Perl have both? What is the intended use, which one should I use in which scenarios? (Example use cases will be appreciated.) Does it matter? (Assuming I don’t mix them.) Does choice of either one affect portability in any way? Which one is more commonly used in modules?
Perl中Cwd :: cwd和Cwd :: getcwd有什么区别,一般来说,不考虑任何特定平台?为什么Perl都有?什么是预期用途,我应该在哪些场景中使用哪一个? (示例用例将受到赞赏。)这有关系吗? (假设我不混合它们。)任何一个的选择是否会以任何方式影响可移植性?哪一个更常用于模块?
Even if I interpret the manual is saying that except for corner cases cwd
is `pwd`
and getcwd
just calls getcwd
from unistd.h
, what is the actual difference? This works only on POSIX systems, anyway.
即使我解释手册是说除了角落情况cwd是`pwd`和getcwd只是从unistd.h调用getcwd,实际的区别是什么?无论如何,这仅适用于POSIX系统。
I can always read the implementation but that tells me nothing about the meaning of those functions. Implementation details may change, not so defined meaning. (Otherwise a breaking change occurs, which is serious business.)
我总是可以阅读实现,但这并没有告诉我这些函数的含义。实施细节可能会发生变化,而非定义的含义。 (否则会发生重大变化,这是一项严肃的事情。)
What does the manual say
Quoting Perl’s Cwd module manpage:
引用Perl的Cwd模块手册页:
Each of these functions are called without arguments and return the absolute path of the current working directory.
这些函数中的每一个都不带参数调用,并返回当前工作目录的绝对路径。
getcwd
GETCWD
my $cwd = getcwd();
我的$ cwd = getcwd();
Returns the current working directory.
返回当前工作目录。
Exposes the POSIX function getcwd(3) or re-implements it if it's not available.
暴露POSIX函数getcwd(3)或重新实现它(如果它不可用)。
cwd
CWD
my $cwd = cwd();
我的$ cwd = cwd();
The cwd() is the most natural form for the current architecture. For most systems it is identical to `pwd` (but without the trailing line terminator).
cwd()是当前架构中最自然的形式。对于大多数系统,它与`pwd`相同(但没有尾随行终止符)。
And in the Notes section:
在Notes部分:
- Actually, on Mac OS, the
getcwd()
,fastgetcwd()
andfastcwd()
functions are all aliases for thecwd()
function, which, on Mac OS, calls `pwd`. Likewise, theabs_path()
function is an alias forfast_abs_path()
- 实际上,在Mac OS上,getcwd(),fastgetcwd()和fastcwd()函数都是cwd()函数的别名,在Mac OS上,它们调用`pwd`。同样,abs_path()函数是fast_abs_path()的别名
OK, I know that on Mac OS1 there is no difference between getcwd()
and cwd()
as both actually boil down to `pwd`
. But what on other platforms? (I’m especially interested in Debian Linux.)
好吧,我知道在Mac OS1上,getcwd()和cwd()之间没有区别,因为它们实际上归结为`pwd`。但是在其他平台上呢? (我对Debian Linux特别感兴趣。)
1 Classic Mac OS, not OS X. $^O
values are MacOS
and darwin
for Mac OS and OS X, respectively. Thanks, @tobyink and @ikegami.
1经典Mac OS,而不是OS X. $ ^ O值分别是Mac OS和OS X的MacOS和darwin。谢谢,@ tobyink和@ikegami。
And a little meta-question: How to avoid asking similar questions for other modules with very similar functions? Is there a universal way of discovering the difference, other than digging through the implementation? (Currently, I think that if the documentation is not clear about intended use and differences, I have to ask someone more experienced or read the implementation myself.)
还有一个小问题:如何避免对功能非常相似的其他模块提出类似的问题?除了深入实施之外,是否存在发现差异的通用方法? (目前,我认为如果文档不清楚预期的用途和差异,我必须要求更有经验的人或自己阅读实施。)
1 个解决方案
#1
8
Generally speaking
I think the idea is that cwd()
always resolves to the external, OS-specific way of getting the current working directory. That is, running pwd
on Linux, command /c cd
on DOS, /usr/bin/fullpath -t
in QNX, and so on — all examples are from actual Cwd.pm
. The getcwd()
is supposed to use the POSIX system call if it is available, and falls back to the cwd()
if not.
我认为这个想法是cwd()总是解析为获取当前工作目录的外部特定于操作系统的方式。也就是说,在Linux上运行pwd,在DOS上运行命令/ c cd,在QNX运行/ usr / bin / fullpath -t,等等 - 所有示例都来自实际的Cwd.pm.如果可用,则getcwd()应该使用POSIX系统调用,否则返回到cwd()。
Why we have both? In the current implementation I believe exporting just getcwd()
would be enough for most of systems, but who knows why the logic of “if syscall is available, use it, else run cwd()
” can fail on some system (e.g. on MorphOS in Perl 5.6.1).
为什么我们两个都有?在当前的实现中,我认为只输出getcwd()对于大多数系统来说已经足够了,但是谁知道为什么“if syscall可用,使用它,否则运行cwd()”的逻辑可能在某些系统上失败(例如在MorphOS上)在Perl 5.6.1)。
On Linux
On Linux, cwd()
will run `/bin/pwd`
(will actually execute the binary and get its output), while getcwd()
will issue getcwd(2)
system call.
在Linux上,cwd()将运行`/ bin / pwd`(实际上将执行二进制并获取其输出),而getcwd()将发出getcwd(2)系统调用。
Actual effect inspected via strace
One can use strace(1)
to see that in action:
可以使用strace(1)来查看实际操作:
Using cwd()
:
使用cwd():
$ strace -f perl -MCwd -e 'cwd(); ' 2>&1 | grep execve
execve("/usr/bin/perl", ["perl", "-MCwd", "-e", "cwd(); "], [/* 27 vars */]) = 0
[pid 31276] execve("/bin/pwd", ["/bin/pwd"], [/* 27 vars */] <unfinished ...>
[pid 31276] <... execve resumed> ) = 0
Using getcwd()
:
使用getcwd():
$ strace -f perl -MCwd -e 'getcwd(); ' 2>&1 | grep execve
execve("/usr/bin/perl", ["perl", "-MCwd", "-e", "getcwd(); "], [/* 27 vars */]) = 0
Reading Cwd.pm
source
You can take a look at the sources (Cwd.pm
, e.g. in CPAN) and see that for Linux cwd()
call is mapped to _backtick_pwd
which, as the name suggests, calls the pwd
in backticks.
您可以查看源代码(Cwd.pm,例如在CPAN中)并查看Linux cwd()调用是否映射到_backtick_pwd,顾名思义,它在反引号中调用pwd。
Here is a snippet from Cwd.pm
, with my comments:
这是Cwd.pm的一个片段,我的评论是:
unless ($METHOD_MAP{$^O}{cwd} or defined &cwd) {
...
# some logic to find the pwd binary here, $found_pwd_cmd is set to 1 on Linux
...
if( $os eq 'MacOS' || $found_pwd_cmd )
{
*cwd = \&_backtick_pwd; # on Linux we actually go here
}
else {
*cwd = \&getcwd;
}
}
Performance benchmark
Finally, the difference between two is that cwd()
, which calls another binary, must be slower. We can make some kind of a performance test:
最后,两者之间的区别在于调用另一个二进制文件的cwd()必须更慢。我们可以做一些性能测试:
$ time perl -MCwd -e 'for (1..10000) { cwd(); }'
real 0m7.177s
user 0m0.380s
sys 0m1.440s
Now compare it with the system call:
现在将它与系统调用进行比较:
$ time perl -MCwd -e 'for (1..10000) { getcwd(); }'
real 0m0.018s
user 0m0.009s
sys 0m0.008s
Discussion, choice
But as you don't usually query the current working directory too often, both options will work — unless you cannot spawn any more processes for some reason related to ulimit
, out of memory situation, etc.
但由于您通常不经常查询当前工作目录,因此两个选项都可以正常工作 - 除非由于某些原因与ulimit,内存不足等情况相关而无法生成任何其他进程。
Finally, as for selecting which one to use: for Linux, I would always use getcwd()
. I suppose you will need to make your tests and select which function to use if you are going to write a portable piece of code that will run on some really strange platform (here, of course, Linux, OS X, and Windows are not in the list of strange platforms).
最后,至于选择使用哪一个:对于Linux,我总是使用getcwd()。我想你需要进行测试并选择使用哪个函数,如果你要编写一个可以在一些非常奇怪的平台上运行的可移植代码(当然,在这里,Linux,OS X和Windows不在奇怪的平台列表)。
#1
8
Generally speaking
I think the idea is that cwd()
always resolves to the external, OS-specific way of getting the current working directory. That is, running pwd
on Linux, command /c cd
on DOS, /usr/bin/fullpath -t
in QNX, and so on — all examples are from actual Cwd.pm
. The getcwd()
is supposed to use the POSIX system call if it is available, and falls back to the cwd()
if not.
我认为这个想法是cwd()总是解析为获取当前工作目录的外部特定于操作系统的方式。也就是说,在Linux上运行pwd,在DOS上运行命令/ c cd,在QNX运行/ usr / bin / fullpath -t,等等 - 所有示例都来自实际的Cwd.pm.如果可用,则getcwd()应该使用POSIX系统调用,否则返回到cwd()。
Why we have both? In the current implementation I believe exporting just getcwd()
would be enough for most of systems, but who knows why the logic of “if syscall is available, use it, else run cwd()
” can fail on some system (e.g. on MorphOS in Perl 5.6.1).
为什么我们两个都有?在当前的实现中,我认为只输出getcwd()对于大多数系统来说已经足够了,但是谁知道为什么“if syscall可用,使用它,否则运行cwd()”的逻辑可能在某些系统上失败(例如在MorphOS上)在Perl 5.6.1)。
On Linux
On Linux, cwd()
will run `/bin/pwd`
(will actually execute the binary and get its output), while getcwd()
will issue getcwd(2)
system call.
在Linux上,cwd()将运行`/ bin / pwd`(实际上将执行二进制并获取其输出),而getcwd()将发出getcwd(2)系统调用。
Actual effect inspected via strace
One can use strace(1)
to see that in action:
可以使用strace(1)来查看实际操作:
Using cwd()
:
使用cwd():
$ strace -f perl -MCwd -e 'cwd(); ' 2>&1 | grep execve
execve("/usr/bin/perl", ["perl", "-MCwd", "-e", "cwd(); "], [/* 27 vars */]) = 0
[pid 31276] execve("/bin/pwd", ["/bin/pwd"], [/* 27 vars */] <unfinished ...>
[pid 31276] <... execve resumed> ) = 0
Using getcwd()
:
使用getcwd():
$ strace -f perl -MCwd -e 'getcwd(); ' 2>&1 | grep execve
execve("/usr/bin/perl", ["perl", "-MCwd", "-e", "getcwd(); "], [/* 27 vars */]) = 0
Reading Cwd.pm
source
You can take a look at the sources (Cwd.pm
, e.g. in CPAN) and see that for Linux cwd()
call is mapped to _backtick_pwd
which, as the name suggests, calls the pwd
in backticks.
您可以查看源代码(Cwd.pm,例如在CPAN中)并查看Linux cwd()调用是否映射到_backtick_pwd,顾名思义,它在反引号中调用pwd。
Here is a snippet from Cwd.pm
, with my comments:
这是Cwd.pm的一个片段,我的评论是:
unless ($METHOD_MAP{$^O}{cwd} or defined &cwd) {
...
# some logic to find the pwd binary here, $found_pwd_cmd is set to 1 on Linux
...
if( $os eq 'MacOS' || $found_pwd_cmd )
{
*cwd = \&_backtick_pwd; # on Linux we actually go here
}
else {
*cwd = \&getcwd;
}
}
Performance benchmark
Finally, the difference between two is that cwd()
, which calls another binary, must be slower. We can make some kind of a performance test:
最后,两者之间的区别在于调用另一个二进制文件的cwd()必须更慢。我们可以做一些性能测试:
$ time perl -MCwd -e 'for (1..10000) { cwd(); }'
real 0m7.177s
user 0m0.380s
sys 0m1.440s
Now compare it with the system call:
现在将它与系统调用进行比较:
$ time perl -MCwd -e 'for (1..10000) { getcwd(); }'
real 0m0.018s
user 0m0.009s
sys 0m0.008s
Discussion, choice
But as you don't usually query the current working directory too often, both options will work — unless you cannot spawn any more processes for some reason related to ulimit
, out of memory situation, etc.
但由于您通常不经常查询当前工作目录,因此两个选项都可以正常工作 - 除非由于某些原因与ulimit,内存不足等情况相关而无法生成任何其他进程。
Finally, as for selecting which one to use: for Linux, I would always use getcwd()
. I suppose you will need to make your tests and select which function to use if you are going to write a portable piece of code that will run on some really strange platform (here, of course, Linux, OS X, and Windows are not in the list of strange platforms).
最后,至于选择使用哪一个:对于Linux,我总是使用getcwd()。我想你需要进行测试并选择使用哪个函数,如果你要编写一个可以在一些非常奇怪的平台上运行的可移植代码(当然,在这里,Linux,OS X和Windows不在奇怪的平台列表)。