2013-03-05 113 views
52

我能够通过如何统计每个目录中的文件数量?

find ./ -type d 

列出所有的目录,我试图列出每个目录的内容,并通过使用以下命令

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

算在每个目录的文件数,但此总结通过

find ./ -type d | xargs ls -l 

返回线的总数是有办法,我可以指望的文件在每个目录有多少?

+0

您是否正在寻找一种方法来计算直接位于'。/'下的每个子目录中的文件数? – Tuxdude 2013-03-05 05:25:48

+4

这是一个偏离主题的问题?我希望看到有选票的人有理由评论! **如果这是题外话,那么这属于哪里?**超级用户?我不这么认为。 – 2013-03-05 08:30:42

+4

shell脚本,批处理脚本正在编程范围内! – 2013-03-05 08:31:42

回答

62

假设你已经GNU发现,让它找到的目录,让庆典做休息:

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

它只是一个与上述不同的版本,所以:(提示:它按名称排序并在csv中排序) for find in x。 -maxdepth 1 -type d | sort';做y ='find $ x | wc -l'; echo $ x,$ y;完成 – peteroak 2013-05-11 17:25:55

+2

如果任何文件名都有空格,这将不起作用。 – 2013-05-12 04:07:01

+3

太棒了!把它放到一行(因此它可以直接用在shell中): 'find。 -type d -print0 |同时读-d''-r dir; do files =(“$ dir”/ *); printf“目录%s中的%5d文件\ n”“$ {#files [@]}”“$ dir”;完成' – lucaferrario 2013-12-12 23:33:12

1

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

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。

+0

这似乎过分复杂。它也让我觉得它为目录层次结构提供了累计计数,例如'./dir1/dir2/dir3'(统计'dir1'及其子目录中的文件,而不是计算'dir1/dir2/dir3'与'dir1/dir2'中的文件分开,并且与'/ dir1'中的文件分开)。 – 2013-03-05 05:45:00

+0

我明白这是作者想要的。如果情况并非如此,那么我同意答案与问题无关。 – Tuxdude 2013-03-05 05:46:33

+0

@JonathanLeffler - 好的,再次阅读这个问题,我意识到你是对的 - 相应地修改了答案。 – Tuxdude 2013-03-05 05:52:06

10

您能安排找到的所有文件,删除文件名,让你对每个文件只包含目录名的行,再算上次数出现的每个目录:

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

这不会输出不包含任何文件的目录名称。不知道这是否是必需的。 – 2013-03-05 05:51:03

+0

确实如此,事实并非如此。 '修复它并不是特别微不足道,因为即使在'find'的输出中出现空目录名也不能保证。有些人可能会:如果有一个文件“dir1/dir2/dir3/file1”,但是“dir1/dir2”只包含子目录(没有纯文件),那么你可以推断它的存在。但是如果'dir1/dir4'没有文件,它的名字根本不会出现。 – 2013-03-05 06:00:35

+0

非常有用的答案,如果你只是想看到当前目录的子目录。 – xixixao 2014-10-21 19:09:39

9

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

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 
+0

对于'find'找到的每个目录运行3个命令('bash','ls','wc')似乎非常昂贵。 – 2013-03-05 05:43:36

+0

@JonathanLeffler同意,因此我的答案的第一行。你的解决方案更好。 – 2013-03-05 05:47:45

+0

很酷这就是我要找的 我可以问最后是' - '吗? – once 2016-03-21 02:58:13

1

我在这里住这一点,未来的提醒

ls |parallel 'echo {} && ls {}|wc -l' 
+0

我的外壳将文件夹着色。我使用'ls --color = never |并行'echo -n {} && ls {} | wc -l'' – 2017-09-20 02:06:07

54

这版画每个目录的当前目录级别的文件数量:

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

如果想要递归地列出顶级目录中的文件数量,那么迄今为止最好的(也是最优雅的)解决方案。 – itoctopus 2017-04-29 13:41:12

+3

这有两个问题:它比每个目录的实际数量多一个文件,并且它将包含当前目录大小的无用行作为“1 _size_”。两者都可以用'du -a |修复sed'/.*\.\/.*\/.*/!d'|剪下-d/-f2 |排序| uniq -c'。添加'| sort -nr'按计数而不是目录名称进行排序。 – dessert 2017-08-04 11:57:05

4

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

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:算上线
+0

修改显示文件首先计算在行上,并按它们排序:'find -type d -readable -exec sh -c'ls -1UA“$ 1”| wc -l | tr -d“\ n”; printf“\ t%s \ n”“$ 1”'sh {}';' | sort -n' – 2017-11-22 15:27:01

0

发现。 -type f -printf'%h \ n'|排序| uniq的-c

给出了例子:

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

这也与遍历LS,而不是找

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

说明来完成:

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

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

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

+0

如果目录名称包含空格,则这不起作用。 – Xylol 2017-10-05 14:45:05

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 
相关问题