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

use*_*637 88 linux bash ubuntu

我能够列出所有目录

find ./ -type d
Run Code Online (Sandbox Code Playgroud)

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

find ./ -type d | xargs ls -l | wc -l
Run Code Online (Sandbox Code Playgroud)

但这总结了返回的总行数

find ./ -type d | xargs ls -l
Run Code Online (Sandbox Code Playgroud)

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

Seb*_*ski 144

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

du -a | cut -d/ -f2 | sort | uniq -c | sort -nr
Run Code Online (Sandbox Code Playgroud)

  • 这有两个问题:每个目录计算一个文件比实际更多,它给出了一个包含当前目录大小的无用行"1 _size_".两者都可以用`du -a |来修复 sed'/.*\.\ /.*//.*/!d'| cut -d/-f2 | 排序| uniq -c`.添加`| sort -nr`按计数而不是目录名排序. (9认同)
  • 到目前为止,如果想要以递归方式列出顶级目录中的文件数,那么这是迄今为止最好(也是最优雅)的解决方案. (6认同)
  • 我想指出的是,这也适用于OSX。(仅将Linux建议复制粘贴到OSX Shell中通常不起作用。) (2认同)
  • 它通过du -a获取不需要的大小.更好的方法是使用find命令.但主要想法是完全一样的:) (2认同)
  • 发现这个对我来说运行得很慢 (2认同)
  • 找 。型f | 切-d / -f2 | 排序| uniq -c | sort -nr#修复了甜点中提到的问题 (2认同)

gle*_*man 96

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

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

  • 我需要在每个子目录中获取所有文件的数量(递归计数).这个修改为您提供:`find.-maxdepth 1-type d -print0 | 读取-d''-r dir; do num = $(找$ dir -ls | wc -l); printf"目录%s中的%5d文件\n""$ num""$ dir"; done` (12认同)
  • 太棒了!把它放在一行(所以它很容易在shell中直接使用):`find.-type d -print0 | 读取-d''-r dir; do files =("$ dir"/*); printf"目录%s中的%5d文件\n""$ {#files [@]}""$ dir"; done` (4认同)
  • 它与上面的版本略有不同,因此:(提示:它按名称排序,并在csv中排序)为find in中的x。-maxdepth 1型d | 排序`; y =`找到$ x | wc -l`; 回声$ x,$ y; 做完了 (2认同)
  • 如果任何文件名都有空格,那将无效. (2认同)

Jon*_*ler 14

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

find . -type f |
sed 's%/[^/]*$%%' |
sort |
uniq -c
Run Code Online (Sandbox Code Playgroud)

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


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

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

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

./dir1/dir2/file1
Run Code Online (Sandbox Code Playgroud)

被替换为

./dir1/
Run Code Online (Sandbox Code Playgroud)

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


Aus*_*ips 12

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

find -type d -print0 | xargs -0 -n1 bash -c 'echo -n "$1:"; ls -1 "$1" | wc -l' --
Run Code Online (Sandbox Code Playgroud)

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

./c/fa/l:0
./a:4
./a/c:0
./a/a:1
./a/a/b:0
Run Code Online (Sandbox Code Playgroud)


Yoo*_* N. 10

Sebastian答案的略微修改版本使用find而不是du(以排除du必须执行且从未使用的与文件大小相关的开销):

 find ./ -mindepth 2 -type f | cut -d/ -f2 | sort | uniq -c | sort -nr
Run Code Online (Sandbox Code Playgroud)

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

  234 dir1
  123 dir2
    1 file1
    1 file2
    1 file3
      ...
    1 fileN
Run Code Online (Sandbox Code Playgroud)

(很像du基于 -based 的变体)

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

{ find ./ -mindepth 2 -type f | cut -d/ -f2 | sort && find ./ -maxdepth 1 -type f | cut -d/ -f1; } | uniq -c | sort -nr
Run Code Online (Sandbox Code Playgroud)

输出将如下所示:

  234 dir1
  123 dir2
   42 .
Run Code Online (Sandbox Code Playgroud)


DCZ*_*DCZ 9

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

  • 这应该是公认的答案。简单易懂。 (3认同)
  • 完美的。并且可以通过将字段说明符替换为字段说明符列表来扩展以对子目录进行计数。例如:“找到”。-类型 f | 切-d/-f2,3 | 排序| 唯一-c` (3认同)
  • 这比公认的答案要好得多,因为您可以获得顶级目录的摘要! (2认同)

o11*_*11c 7

其他人的解决方案都有一个缺点.

find -type d -readable -exec sh -c 'printf "%s " "$1"; ls -1UA "$1" | wc -l' sh {} ';'
Run Code Online (Sandbox Code Playgroud)

说明:

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


Six*_*its 6

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

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

解释:

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

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

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


Tux*_*ude 5

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

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

export -f findfiles

find ./ -type d -exec bash -c 'findfiles "$0"' {} \;
Run Code Online (Sandbox Code Playgroud)

输出示例:

./ 6
./foo 1
./foo/bar 2
./foo/bar/bazzz 0
./foo/bar/baz 4
./src 4
Run Code Online (Sandbox Code Playgroud)

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


小智 5

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

find . -type f -printf "%h\n" | sort | uniq -c
Run Code Online (Sandbox Code Playgroud)

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

使用查找上的更多选项,您可以更加灵活。例如,要获取某个目录中在特定日期修改了多少文件的概览,请使用:

find . -newermt "2022-01-01 00:00:00" -type f -printf "%TY-%Tm-%Td %h\n" | sort | uniq -c
Run Code Online (Sandbox Code Playgroud)

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

请注意,我认为“-printf”可能并非在所有版本的 find 中都可用。