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


103

我可以列出所有目录

find ./ -type d

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

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

但这总和由返回的行数

find ./ -type d | xargs ls -l

有没有一种方法可以计算每个目录中的文件数?


您是否正在寻找一种方法来计算每个子目录中直接位于其下的文件的数量./
Tuxdude

5
这是一个离题的问题吗?我希望看到有投票理由的评论!如果这是题外话,那么这属于哪里?超级用户?我不这么认为..
InfantPro'Aravind”

6
shell脚本,批处理脚本在编程范围内!
InfantPro'Aravind''13

我正要发布Pythonic解决方案,然后我注意到问题已关闭。
anatoly techtonik 2013年

投票重新打开它。在许多情况下,可能还有其他答案可能有用(包括脚本编程,这就是我遇到这个问题的原因)。
lepe

Answers:


109

假设您已找到GNU,请让其查找目录,然后让bash进行其余操作:

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

2
它与上面的版本略有不同,因此:(提示:它按名称和在csv中排序)为x in find . -maxdepth 1 -type d | sort;做y = find $x | wc -l; 回声$ x,$ y; 完成
pcarvalho 2013年

5
太好了!将其放在一行中(这样便于直接在shell中使用):find . -type d -print0 | while read -d '' -r dir; do files=("$dir"/*); printf "%5d files in directory %s\n" "${#files[@]}" "$dir"; done
lucaferrario 2013年

13
我需要获取每个子目录中所有文件的数量(递归计数)。此修改为您提供: 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
OmidS 2015年

1
@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'1

1
@OmidS很棒的oneliner,但是$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
Radek Daniluk

183

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

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

9
如果要递归列出顶级目录中的文件数,则是迄今为止最好的(也是最优雅的)解决方案。
itoctopus

13
这有两个问题:每个目录中的文件数比实际数量多,并且它给出的无用行包含当前目录的大小为“ 1 size ”。两者都可以用固定du -a | sed '/.*\.\/.*\/.*/!d' | cut -d/ -f2 | sort | uniq -c。添加| sort -nr以计数而不是目录名称排序。
甜点,

3
我想指出的是,这也适用于OSX。(仅将Linux建议复制粘贴到OSX shell中通常是行不通的。)
Pistos

2
它获取du -a不需要的大小。更好的方法是使用find命令。但主要思路完全相同:)
Znik

5
找 。型f | 切-d / -f2 | 排序 uniq -c | sort -nr#修复了甜点中提到的问题
jcomeau_ictx

28
find . -type f | cut -d/ -f2 | sort | uniq -c
  • find. -type f 查找类型文件的所有项目
  • cut -d/ -f2 剪出他们特定的文件夹
  • sort 对文件夹名称列表进行排序
  • uniq -c 返回计算每个文件夹名称的次数

8
这比公认的答案好得多,因为您可以获得顶级目录的摘要!
詹森·弗洛伊德

3
这应该是公认的答案。简单易懂。
xssChauhan

1
应该接受的最佳答案就是这个。
loretoparisi

1
简单,优雅,非常适合我的需求。
RichR

完善。并且可以扩展为通过用字段说明符列表替换字段说明符来计数子目录。例如:find . -type f | cut -d/ -f2,3 | sort | uniq -c
藻类

15

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

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

唯一的麻烦是,如果您有任何包含换行符的文件名或目录名,这是不太可能的。如果您真的要担心文件名或目录名中的换行符,建议您找到它们并加以修复,以使它们不包含换行符(并悄悄地使犯罪的一方误解其方式)。


如果您对当前目录的每个子目录中的文件计数感兴趣,对任何子目录中的所有文件以及直接子目录中的文件计数,那么我将sed命令修改为仅打印顶级目录:

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

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

./dir1/dir2/file1

被替换为

./dir1/

第二个替换直接在当前目录中捕获文件;它们的末尾没有斜杠,而是由代替./。然后,排序和计数仅对名称数起作用。


1
这不会输出不包含任何文件的目录名。不知道这是否是必需的。
奥斯汀·菲利普斯

是的,事实并非如此。修复此问题并非易事,因为甚至不能保证空目录名出现在的输出中find。可能有些情况:如果有一个file dir1/dir2/dir3/file1,但dir1/dir2仅包含子目录(没有纯文件),则可以推断出它的存在。但是,如果dir1/dir4没有文件,它的名称就不会出现。
Jonathan Leffler 2013年

如果您只想查看当前目录的子目录,则非常有用的答案。
xixixao 2014年

只是停下来说谢谢。发布此消息3年后,我希望对每个文件夹计算2级文件夹。您的帖子为我节省了很多时间修改sed,查找和知道其他内容
Corvin

13

这是执行此操作的一种方法,但可能不是最有效的方法。

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

它似乎运行三个命令(很贵bashlswc)通过发现每个目录find
乔纳森·莱夫勒

@JonathanLeffler同意,因此我回答的第一行。您的解决方案更好。
奥斯汀·菲利普斯

很酷,这就是我要寻找的东西,请问最后的“-”是什么?
一旦

1
@once-属于bash命令,将由xargs生成。来自man bashA -- signals the end of options and disables further option processing。在这种情况下,这将防止在查找中找到的名称错误的文件成为bash参数处理的一部分。
奥斯汀·菲利普斯

8

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

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:数线

1
修改以首先显示文件计数并对其进行排序:find -type d -readable -exec sh -c 'ls -1UA "$1" | wc -l | tr -d "\n" ; printf "\t%s\n" "$1" ' sh {} ';' | sort -n
Evgeni Sergeev

它执行多次shell,然后速度很慢,并且资源利用率很高。
Znik

6

Sebastian的答案使用的略有修改的版本,find而不是du(排除了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-based的变体)

如果确实也需要计算当前目录中的文件,请使用以下增强版本:

{ 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 .

5

也可以通过遍历ls而不是find来完成

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

说明:

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

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

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


1
如果目录名称包含空格,这将无法正常工作。
木琴

试试for f ./* ; do echo $f $(ls "$f" | wc -l); done
4ndt3s

3

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

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之所以需要,是因为的-exec参数find不允许执行bash函数,除非您显式调用bash,并且需要将当前作用域中定义的函数显式导出到新的shell中。


这似乎过于复杂。在我看来,它还提供了目录层次结构的累加计数,例如./dir1/dir2/dir3(将文件dir1及其子目录中的文件全部计数在一起,而不是将文件中的文件与子目录中的文件dir1/dir2/dir3分开计数)dir1/dir2两者分别不同于/dir1)。
乔纳森·勒夫勒

我知道那是作者想要的。如果不是这种情况,那么我同意答案与问题无关。
Tuxdude

1
@JonathanLeffler-好的,再次阅读问题,我意识到您是对的-相应地修改了答案。
Tuxdude

2

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

我的脚本可以接受path作为起点,并对目录列表进行排序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"

我在stackoverflow中的第一个答案,我希望它可以帮助某人^ _ ^


1

找 。类型的f -printf'%h \ n'| 排序 uniq -c

给出例如:

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

0

我在这里尝试了其他一些方法,但是当我只想要文件时,结果得到了文件计数中包含的子文件夹。打印./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

0

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

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


0

超快速的奇迹命令,它以递归方式遍历文件以计算目录中的图像数量,并按图像扩展名组织输出:

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


0

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

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

0

我编辑了脚本,以排除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 /编辑器排除的路径中,并且其他文件的数量理想情况下不应超过最大值(不过可以更改)。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.