我正在通过 Newbam 的《学习 Bash Shell》一书自学 bash 脚本。我对这本书进展顺利,但对下面的脚本有点困惑。它是一个使用 for 循环来遍历 中的目录$PATH
并打印出有关它们的信息的脚本。脚本是
IFS=:
for dir in $PATH; do
if [ -z "$dir" ]; then dir=.; fi
if ! [ -e "$dir" ]; then
echo "$dir doesn't exist"
elif ! [ -d "$dir" ]; then
echo "$dir isn't a directory"
else
ls -ld $dir
done
我感到困惑的是,为什么如果 dir 为零或不存在,我们是否会将这个空值设置为当前目录?或者我们是否将 dir 更改为当前目录(无论我们碰巧位于哪个目录)?然后该脚本似乎测试 dir 是否存在,然后测试它是否是一个目录。
有人可以帮我解释一下剧本的这方面吗?我本以为如果[ -z "$dir" ]
是真的,这将表明该目录不存在,并且不是一个目录?
答案1
该-z
测试正在测试 中的零长度值$dir
,而不是与实际目录相关的任何内容。如果变量::
中有一个序列,就会触发该条件PATH
,此时我们将$dir
变量的值设置为.
,表示当前目录,然后对其进行标准的两个测试。
答案2
如果 $dir 为空(-z test),则 $dir 设置为 。 (启动脚本的当前目录)。
现在猜测您的 $PATH 格式错误,如 PATH=/bin::/usr/bin:/usr/local/bin 在第二级,您有一个空字段。因此,当该字段为空时,它将被启动脚本的当前目录替换(然后 dir=.)。
答案3
也许缺少一个 elif (else if)。
但是,此脚本旨在列出 $dir 内容,但首先确保
$dir
存在if ! [ -e "$dir" ]
$dir
是目录,而不是文件、管道、develif ! [ -d "$dir" ]
这些测试不能使用 $dir 的空值进行,因此第一行 ( if [ -z "$dir" ]; then dir=.; fi
) 用于将空字符串替换为 。这是一个目录并且存在。
空 $dir 字符串可以有两种方式
PATH=/usr/bin:/sbin::$HOME/bin
PATH=/usr/bin:/sbin:$MYAPPBINDIR:$HOME/bin
(哪里$MYAPPBINDIR
是空的)。
答案4
来自POSIX 规范PATH
(您必须向下滚动一点):
(强调我的)
小路
该变量应表示某些函数和实用程序在搜索仅通过文件名已知的可执行文件时应用的路径前缀序列。前缀应以 ( ':' ) 分隔。当非零长度前缀应用于此文件名时,如果前缀不以 . 结尾,则应在前缀和文件名之间插入 a 。零长度前缀是指示当前工作目录的旧功能。它显示为两个相邻字符 ( "::" )、作为列表其余部分前面的首字母或列表其余部分后面的尾随字符。严格遵守的应用程序应使用实际的路径名(例如 .)来表示 PATH 中的当前工作目录。应从头到尾搜索该列表,将文件名应用于每个前缀,直到找到具有指定名称和适当执行权限的可执行文件。如果正在查找的路径名包含 ,则不应执行通过路径前缀的搜索。如果路径名以 开头,则解析指定的路径(请参阅路径名解析)。如果 PATH 未设置或设置为 null,则路径搜索是实现定义的。由于在此上下文中 是分隔符,因此 PATH 中可能使用的目录名称不应包含字符。
我的假设是 POSIX 规范接受空字符串以适应不使用.
或没有任何特殊名称作为当前工作目录名称的系统。