我试图编写一个 shell 脚本,它将采用目录路径 d 作为参数,并递归地打印 d 中所有文件和目录的深度缩进列表。但是,参数 d 是可选的,如果未给出参数,则将打印当前目录中所有文件和目录的深度缩进列表。这是我的代码:
# the method for tree
myspace=""
spaceCount=0
tree(){
cd "$1"
for i in *; do
if [ -d "$i" ]; then
echo -n "|"
for (( j=0;j<spaceCount;j++ ))
do
echo -n "$myspace"
done
echo "--$i"
spaceCount=$((spaceCount+1))
myspace=" |"
tree "$i"
else
echo -n "|"
for (( j=0;j<spaceCount;j++ ))
do
echo -n "$myspace"
done
echo "--$i"
fi
done
cd ../
spaceCount=$((spaceCount-1))
}
if [ "$1" != "" ]; then
file="$1"
fi
echo ".$file"
tree "$file"
我该如何解决这个问题?
答案1
bash
一般来说,在 和 Bourne 式的 shell中(zsh
例外),像*
这样的不匹配文件的 glob 会扩展为自身(您的脚本使用ksh93
语法,也可以被bash
和识别zsh
,尽管zsh
在默认情况下,对于不匹配的 glob,您会遇到致命错误) 。
echo *
在不包含文件(或仅包含隐藏文件)输出的目录中*
。
for i in *
此处使用for i in *(N)
( zsh
) 或for i in ~(N)*
( ksh93
)来代替,或者如果使用bash
,则设置空球选项(带有shopt -s nullglob
),以便与扩展不匹配的 glob 不执行任何操作。
或者,您可以[ -e "$i" ] || continue
在开头或for
循环中添加一个,通过检查文件是否存在来过滤掉*
(会影响您已读取但不具有搜索权限的目录的行为)。
更多阅读请访问为什么 nullglob 不是默认值?
¹ 在这些目录中,*
将扩展到所有非隐藏文件,但[ -e "$i" ]
会为每个文件返回 false,因为stat()
系统调用将返回没有权限