如何计算每个目录中的文件数?

Posted

技术标签:

【中文标题】如何计算每个目录中的文件数?【英文标题】:How to count number of files in each directory? 【发布时间】:2013-02-19 09:58:15 【问题描述】:

我可以列出所有目录

find ./ -type d

我尝试使用以下命令列出每个目录的内容并统计每个目录中的文件数

find ./ -type d | xargs ls -l | wc -l

但是这总结了返回的总行数

find ./ -type d | xargs ls -l

有没有办法统计每个目录中的文件数?

【问题讨论】:

您是否正在寻找一种方法来统计./ 下的每个子目录中的文件数? 这是一个跑题的问题??我希望看到有理由的近距离投票者! 如果这是题外话,那么它属于哪里? 超级用户?我不这么认为.. shell-script、batch-script在编程范围内! 我正要发布 Pythonic 解决方案,然后我注意到问题已关闭。 投票重新打开它。可能还有其他答案在许多情况下可能有用(包括脚本编程,这就是我提出这个问题的原因)。 【参考方案1】:

这会打印当前目录级别的每个目录的文件计数:

du -a | cut -d/ -f2 | sort | uniq -c | sort -nr

【讨论】:

如果想要递归地列出***目录中的文件数量,这是迄今为止最好(也是最优雅)的解决方案。 这有两个问题:每个目录的一个文件比实际的多,并且它给出了一个无用的行,其中包含当前目录的大小为“1 size”。两者都可以用du -a | sed '/.*\.\/.*\/.*/!d' | cut -d/ -f2 | sort | uniq -c 修复。添加| sort -nr 以按计数而不是目录名称进行排序。 我想指出这也适用于 OSX。 (只是将 Linux 建议复制粘贴到 OSX shell 中通常是行不通的。) 它通过 du -a 获取不需要的大小。更好的方法是使用 find 命令。但主要思想是完全一样的:) 找到 . -类型 f |剪切-d/ -f2 |排序 |唯一的-c | sort -nr # 修复甜点提到的问题【参考方案2】:

假设你有 GNU find,让它找到目录,然后让 bash 完成剩下的工作:

find . -type d -print0 | while read -d '' -r dir; do
    files=("$dir"/*)
    printf "%5d files in directory %s\n" "$#files[@]" "$dir"
done

【讨论】:

它只是一个与上面略有不同的版本,所以:(提示:它按名称和它在 csv 中排序)for x in find . -maxdepth 1 -type d | sort;做 y=find $x | wc -l;回声 $x,$y;完成 太棒了!将其放在一行中(因此可以在 shell 中直接使用):find . -type d -print0 | while read -d '' -r dir; do files=("$dir"/*); printf "%5d files in directory %s\n" "$#files[@]" "$dir"; done 我需要获取每个子目录中所有文件的数量(递归计数)。此修改为您提供:find . -maxdepth 1 -type d -print0 | while read -d '' -r dir; do num=$(find $dir -ls | wc -l); printf "%5d files in directory %s\n" "$num" "$dir"; done @Kory 下面会这样做:find . -maxdepth 1 -type d -print0 | while read -d '' -r dir; do num=$(find "$dir" -ls | wc -l); printf "%5d files in directory %s\n" "$num" "$dir"; done | sort -rn -k1 @OmidS 很棒的单行,但$dir 应该在您的第一条评论中包含在引号内,以正确处理带有空格的目录名称。 :find . -maxdepth 1 -type d -print0 | while read -d '' -r dir; do num=$(find "$dir" -ls | wc -l); printf "%5d files in directory %s\n" "$num" "$dir"; done【参考方案3】:
find . -type f | cut -d/ -f2 | sort | uniq -c
find . -type f 在当前文件夹和子文件夹中查找 file 类型的所有项目 cut -d/ -f2 删除他们的特定文件夹 sort 对文件夹名称列表进行排序 uniq -c 返回每​​个文件夹名称的计数次数

【讨论】:

这比公认的答案要好得多,因为您可以获得***目录的摘要! 这应该是公认的答案。简单易懂。 应该接受的最佳答案是这个。 简单、优雅、完美满足我的需求。 完美。并且可以通过用字段说明符列表替换字段说明符来扩展子目录计数。例如:find . -type f | cut -d/ -f2,3 | sort | uniq -c【参考方案4】:

您可以安排查找所有文件,删除文件名,留下一行仅包含每个文件的目录名,然后计算每个目录出现的次数:

find . -type f |
sed 's%/[^/]*$%%' |
sort |
uniq -c

唯一的问题是如果您有任何包含换行符的文件名或目录名,这是不太可能的。如果您确实需要担心文件名或目录名中的换行符,我建议您找到它们并修复它们,使其不包含换行符(并悄悄地说服有罪的一方他们的方式错误)。


如果您对当前目录的每个子目录中的文件计数感兴趣,计算任何子目录中的任何文件以及直接子目录中的文件,那么我会调整 @ 987654322@命令只打印***目录:

find . -type f |
sed -e 's%^\(\./[^/]*/\).*$%\1%' -e 's%^\.\/[^/]*$%./%' |
sort |
uniq -c

第一个模式捕获名称的开头、点、斜线、直到下一个斜线和斜线的名称,并仅用第一部分替换该行,因此:

./dir1/dir2/file1

被替换为

./dir1/

第二个replace直接捕获当前目录下的文件;它们末尾没有斜线,而是由./ 替换。然后排序和计数仅适用于名称的数量。

【讨论】:

这不会输出不包含任何文件的目录名称。不确定这是否需要。 没错,它没有。 '修复它并不是特别简单,因为空目录名称甚至不能保证出现在find 的输出中。有些可能:如果有一个文件dir1/dir2/dir3/file1,但dir1/dir2 只包含子目录(没有普通文件),那么你可以推断它的存在。但是如果dir1/dir4 没有文件,它的名字就不会出现。 如果您只想查看当前目录的子目录,这是非常有用的答案。 刚刚停下来表示感谢。在此发布 3 年后,我希望计算每个文件夹的 2 级文件夹。你的帖子可能为我节省了很多时间来修补 sed、find 以及谁知道还有什么【参考方案5】:

这是一种方法,但可能不是最有效的。

find -type d -print0 | xargs -0 -n1 bash -c 'echo -n "$1:"; ls -1 "$1" | wc -l' --

给出这样的输出,目录名称后跟该目录中的条目数。请注意,输出计数还将包括可能不是您想要的目录条目。

./c/fa/l:0
./a:4
./a/c:0
./a/a:1
./a/a/b:0

【讨论】:

find找到的每个目录运行3个命令(bashlswc)似乎非常昂贵。 @JonathanLeffler 同意,因此是我回答的第一行。你的解决方案更好。 酷,这就是我要找的东西,请问最后的“--”是什么? @once -- 属于将由 xargs 生成的 bash 命令。来自man bashA -- signals the end of options and disables further option processing。在这种情况下,它将防止在查找过程中发现的错误命名文件成为 bash 参数处理的一部分。【参考方案6】:

使用find 代替du 的Sebastian's 的略微修改版本(以排除du 必须执行且从未使用过的与文件大小相关的开销):

 find ./ -mindepth 2 -type f | cut -d/ -f2 | sort | uniq -c | sort -nr

-mindepth 2 参数用于排除当前目录中的文件。如果你删除它,你会看到一堆类似下面的行:

  234 dir1
  123 dir2
    1 file1
    1 file2
    1 file3
      ...
    1 fileN

(很像基于du 的变体)

如果您还需要计算当前目录中的文件,请使用此增强版:

 find ./ -mindepth 2 -type f | cut -d/ -f2 | sort && find ./ -maxdepth 1 -type f | cut -d/ -f1;  | uniq -c | sort -nr

输出将如下所示:

  234 dir1
  123 dir2
   42 .

【讨论】:

【参考方案7】:

其他人的解决方案都有一个或另一个缺点。

find -type d -readable -exec sh -c 'printf "%s " "$1"; ls -1UA "$1" | wc -l' sh  ';'

解释:

-type d:我们对目录感兴趣。 -readable:我们只希望它们可能列出其中的文件。请注意,find 在尝试在其中搜索更多目录时仍会发出错误,但这会阻止为它们调用 -exec-exec sh -c BLAH sh ';':对于每个目录,运行此脚本片段,$0 设置为 sh$1 设置为文件名。 printf "%s " "$1":可移植且最小限度地打印目录名称,后跟一个空格,而不是换行符。 ls -1UA:按目录顺序列出文件,每行一个(以避免阻塞管道),不包括 特殊目录 ... wc -l:数行数

【讨论】:

修改为首先显示文件计数,并按它们排序:find -type d -readable -exec sh -c 'ls -1UA "$1" | wc -l | tr -d "\n" ; printf "\t%s\n" "$1" ' sh ';' | sort -n 多次执行shell,速度慢,资源利用率高。【参考方案8】:

这也可以通过循环 ls 而不是 find 来完成

for f in */; do echo "$f -> $(ls $f | wc -l)"; done

解释:

for f in */; - 遍历所有目录

do echo "$f -> - 打印出每个目录名

$(ls $f | wc -l) - 为此目录调用 ls 并计算行数

【讨论】:

如果目录名称包含空格,这将无法正常工作。 试试for f ./* ; do echo $f $(ls "$f" | wc -l); done【参考方案9】:

这应该返回目录名,后跟目录中的文件数。

findfiles() 
    echo "$1" $(find "$1" -maxdepth 1 -type f | wc -l)


export -f findfiles

find ./ -type d -exec bash -c 'findfiles "$0"'  \;

示例输出:

./ 6
./foo 1
./foo/bar 2
./foo/bar/bazzz 0
./foo/bar/baz 4
./src 4

export -f 是必需的,因为 find-exec 参数不允许执行 bash 函数,除非您显式调用 bash,并且您需要将当前作用域中定义的函数显式导出到新的 shell。

【讨论】:

这似乎过于复杂了。在我看来,它还提供了诸如./dir1/dir2/dir3 之类的目录层次结构的累积计数(将dir1 及其子目录中的文件一起计数,而不是将dir1/dir2/dir3 中的文件与dir1/dir2 中的文件分开计数,并且两者都与/dir1 中的那些分开)。 我明白这就是作者想要的。如果不是这样,那么我同意答案与问题无关。 @JonathanLeffler - 好的,再次阅读这个问题,我意识到你是对的 - 已经相应地修改了答案。【参考方案10】:

我结合了@glenn jackman's answer和@pcarvalho的答案(在评论列表中,pcarvalho的答案有问题,因为字符'`'(反引号)的额外样式控制功能)。

我的脚本可以接受路径作为augument并将目录列表排序为ls -l,也可以处理“文件名中的空格”问题。

#!/bin/bash
OLD_IFS="$IFS"
IFS=$'\n'
for dir in $(find $1 -maxdepth 1 -type d | sort); 
do
    files=("$dir"/*)
    printf "%5d,%s\n" "$#files[@]" "$dir"
done
FS="$OLD_IFS"

我在***中的第一个答案,希望对大家有所帮助^_^

【讨论】:

【参考方案11】:

这可能是浏览目录结构并提供深度结果的另一种方式。

find . -type d  | awk 'print "echo -n \""$0"  \";ls -l "$0" | grep -v total | wc -l" ' | sh 

【讨论】:

【参考方案12】:

找到 . -type f -printf '%h\n' |排序 | uniq -c

例如:

  5 .
  4 ./aln
  5 ./aln/iq
  4 ./bs
  4 ./ft
  6 ./hot

【讨论】:

【参考方案13】:

我在这里尝试了其他一些,但当我只想要文件时,最终在文件计数中包含了子文件夹。这将打印 ./folder/path<tab>nnn 以及当前文件夹中每个子文件夹的文件数,不包括子文件夹。

for d in `find . -type d -print` 
do 
  echo -e "$d\t$(find $d -maxdepth 1 -type f -print | wc -l)"
done

【讨论】:

【参考方案14】:

我的回答有点不同,由于 find 的选项,您实际上可以更加灵活。试试看:

find . -type f -printf "%h\n" | sort | uniq -c

使用“-printf”的“%h”选项,find 只打印它找到的文件的目录。然后使用“uniq -c”进行排序和计数。这将打印每个目录具有相同目录的搜索结果条目数。

使用更多的查找选项,您可以更加灵活。例如,要了解某个目录在某个日期修改了多少文件,请使用:

find . -newermt "2022-01-01 00:00:00" -type f -printf "%TY-%Tm-%Td %h\n" | sort | uniq -c

这将查找自 2022 年 1 月 1 日以来已修改的所有文件,打印(使用“-printf”)修改日期和目录,然后对它们进行排序和计数。在此示例中,结果中的每一行都有文件数、修改日期(不包括时间)和目录。

请注意,我认为并非所有版本的 find 都提供“-printf”。

【讨论】:

【参考方案15】:

这将给出总数。

for file in */; do echo "$file -> $(ls $file | wc -l)"; done | cut -d ' ' -f 3| py --ji -l 'numpy.sum(l)'

【讨论】:

不,不会。它只会考虑一级子目录。【参考方案16】:

递归查找给定类型文件的简单方法。在这种情况下,当前目录中所有文件夹的 .jpg 文件:

find . -name *.jpg -print | wc -l

【讨论】:

【参考方案17】:

一个超快速的奇迹命令,递归遍历文件,统计一个目录下的图片数量,并按图片扩展名组织输出:

find . -type f | sed -e 's/.*\.//' | sort | uniq -c | sort -n | grep -Ei '(tiff|bmp|jpeg|jpg|png|gif)$'

致谢:https://unix.stackexchange.com/a/386135/354980

【讨论】:

【参考方案18】:

我编辑了脚本以排除所分析目录中的所有node_modules 目录。

这可用于检查项目文件数是否超过文件观察程序可以处理的最大数量。

find . -type d ! -path "*node_modules*" -print0 | while read -d '' -r dir; do
    files=("$dir"/*)
    printf "%5d files in directory %s\n" "$#files[@]" "$dir"
done

检查您的系统可以观看的最大文件数:

cat /proc/sys/fs/inotify/max_user_watches

node_modules 文件夹应添加到慢速系统中的 IDE/编辑器排除路径中,并且其他文件数理想情况下不应超过最大值(尽管可以更改)。

【讨论】:

【参考方案19】:

omg 为什么复杂的命令。只需使用类似的东西

find whatever_folder | wc -l

【讨论】:

因为这不会产生所需的输出。该问题明确要求每个目录中的文件,而不是所有目录的总和。

以上是关于如何计算每个目录中的文件数?的主要内容,如果未能解决你的问题,请参考以下文章

计算不同子目录中的文件数

sh 计算目录中的文件数(递归)

sh 每个子目录中的文件数

计算目录/子目录中的文件数

计算Linux目录中的文件数? [关闭]

计算目录中的文件数