我正在尝试递归遍历 /home 目录中的所有文件。我想对每个文件执行一些 linux 命令。因此,我正在使用 for 循环,如下所示:
for i in /home/**/*
我也将以下语句作为脚本的开头:
- shopt -s globstar
- shopt -s nullglob
但它陷入了 for 循环。这可能是处理这么多文件的问题。如果我给 for 循环一些另一个目录(文件数量较少),那么它会正确遍历。
我还能尝试什么。
完整代码:
#!/bin/bash
shopt -s globstar
shopt -s nullglob
echo "ggg"
for i in /home/**/*
do
NAME=${i}
echo "It's there." $NAME
if [ -f "$i" ]; then
echo "It's there." $NAME
printf "\n\n"
fi
done
答案1
shell需要扩展模式/home/**/*
完全在开始循环的第一次迭代之前。如果您有很多文件,那么自然需要一些时间才能真正开始循环。如果您观察 例如 中的 shell 进程top
,您会注意到它的内存消耗会随着它构建 下所有文件和目录的列表而逐渐增加/home
。
要计算目录结构中常规文件的数量,最好使用find
.
find /home -type f -printf '\n' | wc -l
这将为 中 或 下的每个常规文件打印一行输出/home
,并对wc
这些行进行计数,最后给出总和。
为了避免隐藏文件:
find /home ! -name '.*' -type f -printf '\n' | wc -l
另外要避免隐藏目录(您的 shell 循环也会这样做):
find /home -name '.*' -prune -o -type f -printf '\n' | wc -l
wc -l
我计算空行而不是计算 输出的路径名的原因-print
是路径名可能包含换行符,在这种情况下wc -l
会导致计数错误。
关于符号链接:您的 shell 循环遵循符号链接,因此如果您有符号链接的目录,您的循环将输入这些目录,如果您有指向常规文件的符号链接,您的循环将计算这些目录。
上述解决方案find
将不是遵循符号链接。您可以使用该-L
选项来find
获得类似的行为。
find -L /home -type f -printf '\n' | wc -l
非 GNU 用户find
可以-exec echo \;
使用-printf '\n'
.