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

-3 ls shell bash

为什么bashcsh shellexit status不同?,在man 中: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).
Run Code Online (Sandbox Code Playgroud)

为了测试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
Run Code Online (Sandbox Code Playgroud)

在 Bash 中:

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
Run Code Online (Sandbox Code Playgroud)

它是相同的命令ls,但csh shell和之间的退出状态不同bash

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

现在,问题是:

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

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

Mic*_*mer 7

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

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


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

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


您可以使用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
Run Code Online (Sandbox Code Playgroud)

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