最可靠方式是find+while组合:先用find -maxdepth 1 -type d ! -path "."列出子目录,再对每个目录单独执行find "$dir" -maxdepth 1 -type f | wc -l计数,并加引号防空格、重定向错误输出。

直接统计每个子目录下的文件数
最常用也最可靠的方式是用 find + while 组合:先列出一级子目录,再对每个目录单独执行文件计数。命令如下:
find . -maxdepth 1 -type d ! -path "." | while read dir; do echo "$dir: $(find "$dir" -maxdepth 1 -type f 2>/dev/null | wc -l)"; done- ! -path "." 排除当前目录(.),避免把整个树的文件都算进根目录
-
"$dir" 加双引号,防止路径含空格(如
My Projects)导致命令中断 - 2>/dev/null 屏蔽权限拒绝报错,否则错误信息会混在输出里影响可读性
按深度或范围限制统计
如果只想看某一层级(比如只统计 ./a、./b 这些直接子目录),上面的 -maxdepth 1 已满足。若需跳过某些子目录(比如排除 ./logs),可在 find 列目录时加过滤:
find . -maxdepth 1 -type d ! -path "." ! -name "logs" | while read dir; do ...- 想统计二级子目录(如
./a/x、./b/y),把-maxdepth 1换成-maxdepth 2,但注意这会包含一级和二级目录,需配合-mindepth 2精确限定
按文件类型分组查看各子目录数量
如果关注的是特定后缀(如 .log、.conf)在每个子目录里各有多少个,不能只靠一次 find,得嵌套循环:
for dir in $(find . -maxdepth 1 -type d ! -path "."); do echo "$dir"; for ext in log conf sh; do echo " $ext: $(find "$dir" -maxdepth 1 -type f -name "*.$ext" 2>/dev/null | wc -l)"; done; done- 用
-iname可忽略大小写(如匹配.LOG和.log) - 注意
-name "*.log"不匹配隐藏文件(如.gitignore),如需包含,改用-name ".*.log"单独查,或结合-not -name ".*"排除
为什么不用 tree 或 ls -R 直接解析?
tree 最末行显示总数(如 12 directories, 87 files),但它不提供每个子目录的明细;ls -R 输出结构混乱,夹杂目录头、权限行、总用量等干扰信息,人工或脚本解析容易出错。
更关键的是:tree 默认跳过无权限目录且不提示,ls -R 遇到特殊字符或换行符的文件名也会截断或错位——这些都会让统计结果偏低或不可信。而 find 对路径和权限的处理更可控,适合生产环境使用。


















