如何递归计算多个目录下的文件数量?

如何递归计算多个目录下的文件数量?

我有一个目录,包含很多文件和目录。

我试图获取每个目录中递归包含的文件(和目录)的数量。

我尝试了以下方法:

for dir in $(find -maxdepth 1 -type d); do echo "$dir"; echo find "$dir" | wc -l; done

但这会返回“1”作为每个目录的结果。

我知道还有其他几个问题也有类似的问题,但我真的很想知道上面的代码中我的错误是什么。

答案1

一个 GNU ( bash,wcfind) 解决方案适用于任何路径,甚至包含空格、换行符或以破折号开头的内容:

shopt -s nullglob
for dir in ./*/
do
    printf '%s\n' "$dir"
    find "$dir" -mindepth 1 -printf x | wc --chars
done

解释:

  • 如果不包含目录,该nullglob选项可防止错误。./
  • ./目录中的 glob 确保以短划线 (" ") 开头的文件名不会-混乱echofind.
  • glob 末尾的斜杠确保仅处理目录。
  • -mindepth 1避免计算目录本身。
  • 如果要包含顶层以点开头的目录,则应在循环shopt -s dotglob之前运行for

答案2

这是 bash4+ 的另一种方法。请注意,它遵循符号链接,并且不包含.并且与..l0b0 的答案不同(这可能是也可能不是您想要的):

(
    shopt -s dotglob globstar nullglob
    for dir in */; do
        set -- "$dir"/**/*
        printf '%s: %d\n' "$dir" "$#"
    done
)

答案3

$(find -maxdepth 1 -type d)输出当前目录中的目录列表。除非存在名称以 a 开头的目录.,否则这是一种复杂的编写方式*/。它也是不可靠的:只有当目录名称都不包含空格或通配符时它才有效\[?*。这是因为$(…)只要有空格字符,命令替换的结果就会被分割成单独的单词,并且每个单词都被解释为一个 glob(文件名通配符模式)。您可以通过将命令替换放在双引号 ( "$()") 中来避免此行为,但循环迭代的列表将包含单个元素,该元素是由换行符分隔的目录名称的串联。

请注意这个 shell 编程规则:始终在变量替换和命令替换两边加上双引号( "$foo", "$(foo)") 除非您知道需要省略双引号您知道将它们排除在外是多么安全。

脚本的另一个问题很简单:echo find "$dir"总是打印出一行;你的意思是find "$dir"

for dir in */; do
  echo "$dir"
  find "$dir" | wc -l
done

请注意,只有当该树中没有文件包含换行符时,这才有效。如果可能的话,您可以使find命令打印一些可靠的内容。使用 GNU find(即在非嵌入式 Linux 或 Cygwin 上):

for dir in */; do
  echo "$dir"
  find "$dir" -printf a | wc -c
done

便携:

for dir in */; do
  echo "$dir"
  find "$dir" -exec printf %c {} + | wc -c
done

答案4

使用 GNU Parallel 它将如下所示:

parallel -0 --tag  'find {} |wc -l' ::: */

它将并行find|wc地为每个 CPU 运行一个。根据您的存储系统,并行化可能会提高或降低速度 - 唯一了解的方法就是对其进行测试。进程数可以通过 进行调整-j

GNU Parallel 是一个通用并行器,可以轻松地在同一台计算机或多台您可以通过 ssh 访问的计算机上并行运行作业。

如果您想要在 4 个 CPU 上运行 32 个不同的作业,则并行化的直接方法是在每个 CPU 上运行 8 个作业:

简单的调度

相反,GNU Parallel 在完成后会生成一个新进程 - 保持 CPU 处于活动状态,从而节省时间:

GNU 并行调度

安装

如果您的发行版未打包 GNU Parallel,您可以进行个人安装,不需要 root 访问权限。这样做可以在 10 秒内完成:

(wget -O - pi.dk/3 || curl pi.dk/3/ || fetch -o - http://pi.dk/3) | bash

对于其他安装选项,请参阅http://git.savannah.gnu.org/cgit/parallel.git/tree/README

了解更多

查看更多示例:http://www.gnu.org/software/parallel/man.html

观看介绍视频:https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

浏览本教程:http://www.gnu.org/software/parallel/parallel_tutorial.html

注册电子邮件列表以获得支持:https://lists.gnu.org/mailman/listinfo/parallel

相关内容