当我运行这些命令时,Gnu/Linux 实际上在做什么?
cd; ls /Bin/g* &> /dev/null; echo $?
最终输出为0。
答案1
如果目的是确定g
目录中是否存在以该字母开头的名称/Bin
,那么更好的方法是在bash
shell 中,
shopt -s nullglob
set -- /Bin/g*
if [ "$#" -ne 0 ]; then
printf 'There are %d names starting with "g" in /Bin\n' "$#"
echo 'These are those names:'
printf '\t%s\n' "$@"
else
echo 'No names in /Bin start with "g"'
fi
假设您所在的系统正在运行bash
...
0
如果有名称与模式匹配,则命令集输出,如果没有与该模式匹配的名称,或者某些目录权限不允许,/Bin/g*
则将输出非零值(可能2
,也许,但至少非零)生成列表。1
ls
一开始的cd
是相当无趣的,并且可能不需要(删除此命令会产生影响的情况是相当人为的)。它将您的当前目录更改为任何值,或者如果未设置,则更改$HOME
为由/etc/passwd
(或等效数据库)定义的主目录。HOME
在执行命令之前ls
,shell 会将/Bin/g*
模式扩展为匹配名称的列表。如果您有权读取 的目录列表/Bin
,并且/Bin
目录中存在以字母 开头的名称g
,那么这些名称的列表将替换作为 的参数的模式ls
。如果没有匹配项,或者您没有正确的访问权限/Bin
,则模式将按原样保留。
执行时ls
,它会获取 shell 扩展提供给它的参数列表,/Bin/g*
并尝试列出这些名称。鉴于这些名称存在,并且您有权列出任何子目录以/Bin
字母开头的g
命令ls
最终将成功终止并返回退出状态0
。如果名字是这样的话不是存在,或者如果其中一个名称引用了您无权列出其内容的子目录,则它将失败并返回非零退出状态(在这些情况下GNUls
返回)。2
这&>/dev/null
是一个重定向,在bash
shell 中,会将标准输出流和标准错误流重定向到/dev/null
.运行时ls
,这意味着该命令的所有输出和所有错误都将被丢弃(/dev/null
是一个特殊的设备文件,写入时会丢弃所有数据)。重定向&>
运算符不是标准的,最好写成>/dev/null 2>&1
,即“将标准输出重定向到/dev/null
,然后将标准错误重定向到标准输出所在的位置”。从技术上讲,此步骤甚至在 shell 扩展/Bin/g*
通配模式之前就已发生。
最终echo $?
输出最近的退出状态。这将是 的退出状态ls
(或者可能是由于未能扩展模式而导致的错误代码,或者可能是由于在 中找不到而根本/Bin/g*
无法运行而导致的错误代码,请参见下文)。ls
$PATH
有两个 shell 选项会影响这一点:
如果
nullglob
在当前 shell 会话中设置该选项,则模式/Bin/g*
将为完全移除而不是被保留。这意味着它将ls
在没有参数的情况下运行,并且它将列出当前的目录(之后可能是您的主目录cd
)。如果您有权读取当前目录,则此操作将会成功。如果您无权读取目录内容,ls
将返回非零退出状态(在这种情况下GNUls
将返回)。1
如果
failglob
设置了 shell 选项并且没有名称与模式匹配/Bin/*
,则壳会抱怨,no match: /Bin/g*
并且您会得到非零退出状态(可能1
;甚至ls
根本不会运行)。由于是 shell 产生错误消息,并且 shell 的标准错误流是不是发送到
/dev/null
(请记住,这只是ls
重定向的输出流,在这种情况下甚至不会运行)此错误消息将在最终打印ls
之前打印在您的终端中。echo $?
1
一个 shell 变量会影响这一点:
当 shell 扩展未加引号的值时,该
IFS
变量生效。这就是您在最后一步 (echo $?
) 中所做的事情。当 shell 扩展$?
为能够使用正确的值进行调用时,它首先使用 中的字符作为分隔echo
符将值拆分为单词。$IFS
默认情况下,$IFS
是一个空格、一个制表符和一个换行符。如果
IFS
要设置为字符串(这些是if using和 GNU012
的可能值),那么 shell 会将值( 的退出状态)拆分为空字符串(因为该值将被视为分隔符split on),并且将在没有参数的情况下调用,产生一个单独的换行符作为输出。$?
bash
ls
$?
ls
echo
为了避免这种不幸的情况,您可以使用
echo "$?"
(注意 的双引号$?
)。
不包括:
PATH
ls
以及如果在 中找不到会发生什么和不会发生什么$PATH
,以及为什么这不会影响cd
和echo
。- 所有与实际执行命令相关的事情,
fork
+exec
等。 - 别名扩展或覆盖任何工具的 shell 函数
cd
,ls
或者echo
。 - 在非
bash
shell 中会发生什么以及为什么? - 的效果
set -f
。