我有一个目录,包含很多文件和目录。
我试图获取每个目录中递归包含的文件(和目录)的数量。
我尝试了以下方法:
for dir in $(find -maxdepth 1 -type d); do echo "$dir"; echo find "$dir" | wc -l; done
但这会返回“1”作为每个目录的结果。
我知道还有其他几个问题也有类似的问题,但我真的很想知道上面的代码中我的错误是什么。
答案1
一个 GNU ( bash
,wc
和find
) 解决方案适用于任何路径,甚至包含空格、换行符或以破折号开头的内容:
shopt -s nullglob
for dir in ./*/
do
printf '%s\n' "$dir"
find "$dir" -mindepth 1 -printf x | wc --chars
done
解释:
- 如果不包含目录,该
nullglob
选项可防止错误。./
./
目录中的 glob 确保以短划线 (" ") 开头的文件名不会-
混乱echo
或find
.- 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 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