【问题标题】:Strange `pwd` output from perlperl 的奇怪“pwd”输出
【发布时间】:2011-09-27 11:12:23
【问题描述】:

我有一个非常简短的 perl 脚本教程:

#!/usr/bin/perl
print "The date is ",`date`;
print "The date is `date`",".\n";
$directory=`pwd`;
print "\nThe current directory is $directory.";

和输出:

The date is Sat Jul  2 17:04:58 PDT 2011
The date is `date`.

The current directory is total 20
-rwxr-xr-x 1 yan yan 433 2011-07-02 15:58 36
-rwxr-xr-x 1 yan yan 313 2011-07-02 16:29 43
-rwxr-xr-x 1 yan yan 116 2011-07-02 16:51 45
-rwxr-xr-x 1 yan yan 149 2011-07-02 16:53 46
-rwxr-xr-x 1 yan yan 145 2011-07-02 17:02 47

但是如果我只运行 pwd 我得到了:

yan@ubuntu:~/bin/blackperl$ pwd
/home/yan/bin/blackperl

对这里的奥秘有什么合乎逻辑的解释吗?非常感谢!

【问题讨论】:

  • 当我运行你的脚本时,输出的最后一行是:The current directory is /home/user/asdf 所以我不知道。我猜你的环境中的某些东西可能会扭曲结果。
  • 我使用的是 Ubuntu 9.10。似乎在输出“ls -l”,但由于“pwd”在 shell 下工作正常……很奇怪
  • 可能是您的 perl 使用另一个 shell 进行 `` 调用,而不是您用于比较的,因此有其他设置? print type pwd; 在 perl 中打印什么? (里面有反引号)?
  • 在Ubuntu中,脚本执行的默认shell是dash,而用户交互的默认shell是bash。我想 Perl 会调用第一个,并且您在破折号初始化脚本中定义了一些别名。
  • @Paŭlo Ebermann,Perl 在需要 shell 时使用 /bin/sh,尽管在这种情况下它根本不使用 shell。

标签: linux perl unix ubuntu pwd


【解决方案1】:

我也无法解释其中的奥秘,但您可以尝试使用 Perl Core 模块 Cwd 而不是 pwd 命令:

use warnings;
use strict;
use Cwd;
my $dir = getcwd();
print "$dir\n";

一个优点是Cwdpwd 更便携。

另见:UNIX 'command' equivalents in Perl

【讨论】:

    【解决方案2】:

    谜团的可能解释

    在命令搜索路径(即在 PATH 环境变量命名的目录之一)中有一些名为 pwd 的程序会执行这些奇怪的事情。在交互式 shell (bash) 或 shell 脚本 (dash) 中执行 pwd 时,您会得到内置命令 pwd,它会按原样打印当前工作目录。

    另一方面,在您的 Perl 源代码行中

    $directory=`pwd`;
    

    Perl 不使用 C 的 system() 函数调用系统的 shell,而是直接执行路径中的 pwd 命令(在分叉进程中使用 execvp() 调用),因为该命令看起来很简单(一个简单的命令,在 bash 术语中)。如果这个pwd 二进制文件不是通常的/bin/pwd 二进制文件(它也只是打印当前目录),而是执行类似ls -l 的操作,我们会得到观察到的行为。

    真正的解决方案是修复您的 PATH 和/或删除伪造的 pwd 二进制文件。使用 which pwd 找出它在哪里(或在 bash 上使用 type -a pwd)。

    Perl 方面的解决方案是强制执行 shell 调用:

    $directory=`pwd;`;
    

    这迫使 Perl 调用 shell 而不是直接执行程序。 (更一般地说,任何 shell 元字符 都有这种效果。这仅针对 Perl 的 system function 进行描述,不适用于 quote-execute operator。)

    在这种情况下,Perl 将调用 /bin/sh,在 Ubuntu(至少在当前版本中,我不确定你的 9.10)是 dash(Debian Almquist Shell)而不是 bash(GNU 的 Bourne Again)贝壳)。 Dash 是一个比 bash 更简单(也更快)的sh 实现,但是对于像pwd 这样的东西应该没有区别(它也是我的 dash 中的一个内置),只要你没有别名或 shell 函数在一个 shell 中定义,而不是在另一个 shell 中。

    当然,更好的解决方案是使用 Perl 的 Cwd 模块,如 recommended in the answer by toolic


    感谢 ikegami 在问题的 cmets 中向我解释了反引号运算符的语义。

    【讨论】:

    • 哇,你太棒了!你就像夏洛克·福尔摩斯在没有到现场的情况下看到了犯罪现场!我确实在 $PATH 文件夹中找到了一个名为 pwd 的可执行文件!我什至不记得了,但是在阅读了您的回复后,我检查了……并找到了丢失的线索!非常感谢您,非常感谢您富有洞察力的回答!
    • 我很高兴看到我在这里猜到了。在 ikegami 澄清了 qx-operator 的工作原理之后,真的没有其他原因了。
    【解决方案3】:

    在这里也可以正常工作(SUSE Linux Enterprise Server)。我不知道为什么$directory 会吐出ls 的输出。

    ETA:从命令行运行:

    perl -e 'print "$ENV{PWD}\n";'

    告诉我输出是什么。

    【讨论】:

      【解决方案4】:

      它对我也很好。我想知道它是否可能与 shell 别名或 shell 函数有关。您可以像这样在 bash 中将一个命令别名为另一个命令:

      doug@supermicro:~$ alias pwd='ls -la'
      

      这里有更多关于别名的信息:http://en.wikipedia.org/wiki/Alias_%28command%29

      虽然我想不出为什么 Perl 程序运行的 shell 命令可以访问与您可以访问的集合不同的一组别名。

      你是从命令行运行这个程序还是通过另一个进程运行它? (例如由 Apache 用户帐户运行的 CGI 脚本)

      您还可以定义与外部命令同名并运行而不是外部命令的 shell 函数,但这并不能解释为什么您可以直接从命令行获得正常输出。

      【讨论】:

      • Perl 不为 qx{pwd} 使用 shell。试试:alias pwd='ls -la',然后是 pwd,然后是 perl -e'print qx{pwd}'qx{} 和反引号是一样的,但是反引号会与 SO 的标记发生冲突。)
      猜你喜欢
      • 2019-11-22
      • 1970-01-01
      • 2021-12-03
      • 2015-02-18
      • 2011-06-14
      • 2013-06-04
      • 2021-02-08
      • 2014-12-27
      • 1970-01-01
      相关资源
      最近更新 更多