为什么 bash 和 csh shell 中命令“ls”的退出状态不同?

为什么 bash 和 csh shell 中命令“ls”的退出状态不同?

为什么exit status之间不同巴什外壳程序?, 在ls男人:

Exit status:
       0      if OK,

       1      if minor problems (e.g., cannot access subdirectory),

       2      if serious trouble (e.g., cannot access command-line
              argument).

为了测试exit status命令ls,假设我们有一个名为ss保存在文件夹中的文件。让我们使用通配符根据其字符的状态列出该文件?

在 csh 外壳中:

ls -d ss
ss

ls -d s?
ss

ls -d ?s
ss

ls -d ?z
ls: No match.

ls -d ?z | echo $?  #check exit status
0

在重击中:

ls -d ss
ss

ls -d s?
ss

ls -d ?s
ss

ls -d ?z
ls: cannot access ?z: No such file or directory

ls -d ?z | echo $?  #check exit status
2

这是相同的命令,但和ls之间的退出状态不同:csh shellbash

  • 在 csh shell 中退出状态是0
  • 在 bash 中退出状态是2

现在,问题是:

1)为什么相同的命令ls在 bash 和 csh shell 中具有不同的退出状态?

2) bash 和 csh shell 下命令行为的这种差异有何重要性?

答案1

首先,你ls -d ?z | echo $?在 Bash 中的衡量并不是你所认为的。管道全部立即启动,参数扩展甚至在此之前发生,因此echo $?打印返回代码以前的命令,而不是管道之前的命令。在 csh 下,它甚至不这样做。那个输出是没有意义的。如果您将它们作为单独的命令运行:ls -d ?z ; echo $?您将获得有关实际退出代码的信息输出。

sh -c 'exit 53'将作为测试您是否真正从您想要的位置获取退出代码的命令。


其次,虽然您没有告诉我们,但第一个示例中的错误听起来像 csh,所以我假设就是这样。在这种情况下,ls -d ?zls根本没有运行; shell 的通配符扩展失败并No match报告错误 (" "),从而阻止命令运行。默认情况下,Bash 按字面意思传递不匹配的通配符:实际上,它运行ls '?z',并且您收到错误,ls因为该文件不存在。无论如何,报告的错误代码来自上一行。

因此,该ls命令在运行时在所有情况下都有相同的行为,只是有时它没有运行。


你可以改变 Bash 的(坦率地说,不好的)行为shopt -s failglob。当 glob 不匹配时,它将出错:

/tmp$ ls ?z
ls: cannot access '?z': No such file or directory
/tmp$ shopt -s failglob
/tmp$ ls ?z
bash: no match: ?z

第一个的退出代码为 2,来自ls,第二个的$?退出代码为 1,来自 Bash 本身。

相关内容