for循环中的glob运算符的问题

for循环中的glob运算符的问题

我正在尝试递归遍历 /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'.

相关内容