【问题标题】:Shell: list directories ordered by file count (including in subdirectories)Shell:列出按文件数排序的目录(包括子目录)
【发布时间】:2011-08-02 20:17:31
【问题描述】:

我的 Linux 主目录中允许的文件数量几乎达到了我的限制,我很好奇所有文件的位置。

在任何目录中,我可以使用例如find . -type f | wc -l 来显示该目录及其子目录中有多少文件,但我想要的是能够生成所有子目录的完整列表(和子子目录等),每个文件都有 count 包含在其中的所有文件和 子目录 - 如果可能,按数量降序排列。

例如,如果我的文件结构如下所示:

Home/
  file1.txt
  file2.txt
  Docs/
    file3.txt
    Notes/
      file4.txt
      file5.txt
    Queries/
      file6.txt
  Photos/
    file7.jpg

输出会是这样的:

7  Home
4  Home/Docs
2  Home/Docs/Notes
1  Home/Docs/Queries
1  Home/Photos

非常感谢任何建议。 (也是答案的快速解释,所以我可以从中学习!)。谢谢。

【问题讨论】:

  • 是什么让您认为您接近每个目录的文件限制?我知道的每个目录的文件的任何限制都不需要计算每个子目录的文件,只需要直接在这个目录中的文件......可能你的意思是“每个分区的索引节点”?
  • 我认为这是我在系统上拥有的文件总数(这是系统管理员给出的解释的要点......)。我想要的是查找是否有一个大文件夹,里面装满了我可以删除的旧缓存文件或日志或崩溃报告。
  • ... 例如在名为 .../.metadata/.plugins/org.eclipse.epp.usagedata.recording 的隐藏文件夹中的 10000 个文件 - blimey!
  • du ~/* | sort -n 会给你一个目录大小的排序列表,这可能也很有用
  • 谢谢@otto,很高兴知道这一点。

标签: linux unix shell command-line


【解决方案1】:

我使用以下命令

find . -xdev -type f | cut -d "/" -f 2 | sort | uniq -c | sort -n

这会产生类似的东西:

[root@ip-***-***-***-*** /]# find . -xdev -type f | cut -d "/" -f 2 | sort | uniq -c | sort -n
      1 .autofsck
      1 stat-nginx-access
      1 stat-nginx-error
      2 tmp
     14 boot
     88 bin
    163 sbin
    291 lib64
    597 etc
    841 opt
   1169 root
   2900 lib
   7634 home
  42479 usr
  80964 var

【讨论】:

  • 这似乎是最有效的解决方案,因为它不会为每个要计数的文件派生一个新进程,而是使用单个“剪切”命令处理大量文件。跨度>
【解决方案2】:

这应该可行:

find ~ -type d -exec sh -c "fc=\$(find '{}' -type f | wc -l); echo -e \"\$fc\t{}\"" \; | sort -nr

说明: 在上面的命令中会运行“find ~ -type d”来查找home-directory的所有子目录。对于它们中的每一个,它都会运行一个简短的 shell 脚本来查找该子目录中的文件总数(使用您已经知道的“find $dir -type f | wc -l”命令),并将回显该数字后跟目录名称。然后运行 ​​sort 命令以按文件总数降序排序。

这不是最有效的解决方案(你最终会多次扫描同一个目录),但我不确定你是否可以用一个衬里做得更好:-)

【讨论】:

  • 谢谢,这行得通,但它会创建一个很长的列表!我想我应该问是否可以只列出前 50 个结果...
  • 在最后加“|head -50”即可。
  • 糟糕,当我在本地尝试它时(在我的笔记本电脑 HD 上,作为测试)它有效,但是当我 ssh 进入我真正需要它的服务器时,我收到一个错误:Unmatched ".
  • 也许 /bin/sh 不是您服务器上的 bash?尝试用 'bash' 替换上述命令中的 'sh'。
  • @hochi: 如find ~ -print0 -type d...fc=\$(find '{}' -print0 -type f...?
【解决方案3】:
countFiles () {
    # call the recursive function, throw away stdout and send stderr to stdout
    # then sort numerically
    countFiles_rec "$1" 2>&1 >/dev/null | sort -nr
}

countFiles_rec () {
    local -i nfiles 
    dir="$1"

    # count the number of files in this directory only
    nfiles=$(find "$dir" -mindepth 1 -maxdepth 1 -type f -print | wc -l)

    # loop over the subdirectories of this directory
    while IFS= read -r subdir; do

        # invoke the recursive function for each one 
        # save the output in the positional parameters
        set -- $(countFiles_rec "$subdir")

        # accumulate the number of files found under the subdirectory
        (( nfiles += $1 ))

    done < <(find "$dir" -mindepth 1 -maxdepth 1 -type d -print)

    # print the number of files here, to both stdout and stderr
    printf "%d %s\n" $nfiles "$dir" | tee /dev/stderr
}


countFiles Home

生产

7 Home
4 Home/Docs
2 Home/Docs/Notes
1 Home/Photos
1 Home/Docs/Queries

【讨论】:

  • 感谢 glenn - 很抱歉很密集,但是要使用它,我需要将函数定义放在某个文件中吗?
  • 是的。如果您正在编写脚本,只需将它们添加到该文件中即可。
  • 您甚至不需要将其放入文件中,您可以将函数直接粘贴到当前提示符中,bash 将为您定义函数。
  • 请注意,这仅适用于 bash,不适用于 shell 本身(sh 报告 done &lt; &lt;(find "$dir" -mindepth 1 -maxdepth 1 -type d -print)' 的语法错误)
【解决方案4】:

更简单更高效:

find ~ -type f -exec dirname {} \; | sort | uniq -c | sort -nr

【讨论】:

  • 这不包括子目录计数。
【解决方案5】:
find . -type d -exec sh -c '(echo -n "{} "; ls {} | wc -l)' \; | sort -n -k 2

这非常有效。

它将按升序显示计数(即最后最大)。要使其按降序排列,请将“-r”选项添加到“排序”。

如果您在“/”目录中运行此命令,它将扫描整个文件系统并告诉您包含最多文件和子目录的目录是什么。这是查看所有 inode 的使用位置的好方法。

注意:这不适用于包含空格的目录,但如果对您有问题,您可以修改它以在这种情况下工作。

【讨论】:

    【解决方案6】:

    参见以下示例:按第 2 列反向排序。使用sort -k 2 -r。 -k 2 表示按第 2 列排序(空格分隔),-r 表示反向。

    # ls -lF /mnt/sda1/var/lib/docker/165536.165536/aufs/mnt/ | sort -k 2 -r
    total 972
    drwxr-xr-x   65 165536   165536        4096 Jun  5 12:23 ad45ea3c6a03aa958adaa4d5ad6fc25d31778961266972a69291d3664e3f4d37/
    drwxr-xr-x   19 165536   165536        4096 Jun  6 06:46 7fa7f957669da82a8750e432f034be6f0a9a7f5afc0a242bb00eb8024f77d683/
    drwxr-xr-x    2 165536   165536        4096 May  8 02:20 49e067ffea226cfebc8b95410e90c4bad6a0e9bc711562dd5f98b7d755fe6efb/
    drwxr-xr-x    2 165536   165536        4096 May  8 01:19 45ec026dd49c188c68b55dcf98fda27d1f9dd32f825035d94849b91c433b6dd3/
    drwxr-xr-x    2 165536   165536        4096 Mar 13 06:08 0d6e95d4605ab34d1454de99e38af59a267960999f408f720d0299ef8d90046e/
    drwxr-xr-x    2 165536   165536        4096 Mar 13 02:25 e9b252980cd573c78065e8bfe1d22f01b7ba761cc63d3dbad284f5d31379865a/
    drwxr-xr-x    2 165536   165536        4096 Mar 13 02:24 f4aa333b9c208b18faf00b00da150b242a7a601693197c1f1ca78b9ab2403409/
    drwxr-xr-x    2 165536   165536        4096 Mar 13 02:24 3946669d530695da2837b2b5ed43afa11addc25232b29cc085a19c769425b36b/
    drwxr-xr-x    2 165536   165536        4096 Mar 11 11:11 44293f77f63806a58d9b97c3c9f7f1397b6f0935e236250e24c9af4a73b3e35b/
    

    【讨论】:

      【解决方案7】:

      但是,如果您对使用 dirname 的非累积解决方案感到满意(请参阅 wjb 的答案),那么效率更高的是:

      find ~ -type f -print0 | xargs -0 dirname | sort | uniq -c | sort -n
      

      请注意,这不会显示空目录。为此,您可以这样做 查找 ~ -type d -empty 如果您的 find 版本支持它。

      【讨论】:

      • 嗯,因为目录名在那里,所以路径丢失了。我的猜测是 xargs -0 在您的系统上不起作用,或者您有名为“”的文件,即文件名仅由空格组成。后者是可能的,但很奇怪:
      • 实际上我刚刚测试了空白文件/目录( touch " " 和 mkdir " " 来创建这些奇怪的东西)并且该命令仍然有效。但是,find -print0 | xargs -0 并不总是存在于 cf : gnu.org/software/findutils/manual/html_mono/find.html .
      猜你喜欢
      • 2017-10-08
      • 1970-01-01
      • 2018-05-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-04
      • 1970-01-01
      相关资源
      最近更新 更多