如何按大小对 du -h 输出进行排序

Tom*_*ner 1224 linux bash gnu du

我需要获取人类可读的 du 输出列表。

但是,du没有“按大小排序”选项,并且管道sort无法与人类可读标志一起使用。

例如,运行:

du | sort -n -r 
Run Code Online (Sandbox Code Playgroud)

按大小(降序)输出排序的磁盘使用情况:

du |sort -n -r
65108   .
61508   ./dir3
2056    ./dir4
1032    ./dir1
508     ./dir2
Run Code Online (Sandbox Code Playgroud)

但是,使用人类可读的标志运行它,排序不正确:

du -h | sort -n -r

508K    ./dir2
64M     .
61M     ./dir3
2.1M    ./dir4
1.1M    ./dir1
Run Code Online (Sandbox Code Playgroud)

有谁知道du -h 按大小排序的方法?

ptm*_*man 1719

从2009 年 8 月发布的GNU coreutils 7.5开始,sort允许使用一个-h参数,该参数允许以下类型的数字后缀du -h

du -hs * | sort -h
Run Code Online (Sandbox Code Playgroud)

如果您使用的排序不支持-h,您可以安装 GNU Coreutils。例如在较旧的 Mac OS X 上:

brew install coreutils
du -hs * | gsort -h
Run Code Online (Sandbox Code Playgroud)

sort 手册

-h, --human-numeric-sort compare human readable numbers (e.g., 2K 1G)

  • 好一个!我个人总是做`du -BM | sort -nr` 作为一种解决方法 - 如果有人坚持使用较旧的 coreutils,它具有足够的人类可读性,并且已排序。 (45认同)
  • 使用自制软件在 OS X 上轻松安装 -- brew install coreutils。 (32认同)
  • 如果通过 Homebrew 在 OSX 上使用,请注意您现在需要使用 gsort 而不是 sort:`du -hs * | gsort -h` (32认同)
  • 手册的相关部分:http://www.gnu.org/software/coreutils/manual/coreutils.html#sort-invocation (4认同)
  • @PaulDraper,`du -BM` 以兆字节为单位打印所有内容,因此 168K 的文件实际上会显示为 0M。除非有一些我不知道的其他版本差异。我的 `du` 版本只显示整数兆字节值。 (2认同)
  • 对于像我这样的未来 Google 用户,如果您想使用此答案的命令,但按大小降序而不是升序排序,则只需要“size”的“-r”选项。要滚动最大内容的列表,请使用`du -hs * | 排序-hr | 少`。 (2认同)
  • 我使用`du -sh ./* | sort -g` 因为 BusyBox v1.27.2 不支持 `-h` (2认同)
  • 更简单:`du -h | 排序-h` (2认同)

cad*_*ian 100

du | sort -nr | cut -f2- | xargs du -hs
Run Code Online (Sandbox Code Playgroud)

  • 它会做大量的重复计数。 (58认同)
  • @Douglas Leeder:您对重复计数是正确的,但认为第二个 du 不是从冷缓存开始(感谢操作系统)@hasen j:xargs 是一个非常有用的命令,它拆分标准输入并将其作为参数提供到给定的命令 (8认同)
  • Chris's 实际上更胜一筹,因为它适用于包含空格的路径。以你的方式投出一票,伙计。 (4认同)
  • 丑陋,但跨平台:)。 (3认同)

小智 72

我使用了一个非常有用的工具,称为ncdu,旨在查找那些讨厌的高磁盘使用文件夹和文件,并将其删除。它基于控制台,快速而轻便,并且在所有主要发行版上都有软件包。

  • [gt5](http://gt5.sourceforge.net/) 同理;它的杀手锏是显示增长。 (8认同)
  • 这太酷了!如果你只想识别大目录,比使用 `du` 快得多。 (2认同)

Ada*_*ire 68

@Douglas Leeder,还有一个答案:使用另一种工具对 du -h 的人类可读输出进行排序。像 Perl!

du -h | perl -e 'sub h{%h=(K=>10,M=>20,G=>30);($n,$u)=shift=~/([0-9.]+)(\D)/;
return $n*2**$h{$u}}print sort{h($b)<=>h($a)}<>;'
Run Code Online (Sandbox Code Playgroud)

拆分为两条线以适合显示。您可以以这种方式使用它,也可以将其设为单线,无论哪种方式都可以使用。

输出:

4.5M    .
3.7M    ./colors
372K    ./plugin
128K    ./autoload
100K    ./doc
100K    ./syntax
Run Code Online (Sandbox Code Playgroud)

编辑:PerlMonks打了几轮高尔夫球后,最终结果如下:

perl -e'%h=map{/.\s/;99**(ord$&&7)-$`,$_}`du -h`;die@h{sort%h}'
Run Code Online (Sandbox Code Playgroud)

  • 由于“die”,您的简短版本在“stderr”上输出,您可以更改它以使其在“stdout”上输出吗? (2认同)
  • 将 `die` 更改为 `print`,它将转到 `stdout`。只是多了两个字符。 (2认同)

小智 47

du -k * | sort -nr | cut -f2 | xargs -d '\n' du -sh
Run Code Online (Sandbox Code Playgroud)


Dou*_*der 24

据我所知,您有三个选择:

  1. du在显示之前更改为排序。
  2. 改变sort以支持数字排序的人类大小。
  3. 对 sort 的输出进行后处理以将基本输出更改为人类可读。

您也可以du -k使用 KiB 中的大小。

对于选项 3,您可以使用以下脚本:

#!/usr/bin/env python

import sys
import re

sizeRe = re.compile(r"^(\d+)(.*)$")

for line in sys.stdin.readlines():
    mo = sizeRe.match(line)
    if mo:
        size = int(mo.group(1))
        if size < 1024:
            size = str(size)+"K"
        elif size < 1024 ** 2:
            size = str(size/1024)+"M"
        else:
            size = str(size/(1024 ** 2))+"G"

        print "%s%s"%(size,mo.group(2))
    else:
        print line
Run Code Online (Sandbox Code Playgroud)


Joa*_*uer 24

我也遇到过这个问题,我目前正在使用一种解决方法:

du -scBM | sort -n
Run Code Online (Sandbox Code Playgroud)

这不会产生缩放值,但总是产生以兆字节为单位的大小。这还不够完美,但对我来说,总比没有好(或以字节为单位显示大小)。


Ada*_*ire 21

别处找到了这个帖子。因此,此 shell 脚本将执行您想要的操作,而无需du两次调用所有内容。它用于awk将原始字节转换为人类可读的格式。当然,格式略有不同(所有内容都打印到一位小数精度)。

#/bin/bash
du -B1 | sort -nr  |awk '{sum=$1;
hum[1024**3]="G";hum[1024**2]="M";hum[1024]="K";
for (x=1024**3; x>=1024; x/=1024){
        if (sum>=x) { printf "%.1f%s\t\t",sum/x,hum[x];print $2;break
}}}'
Run Code Online (Sandbox Code Playgroud)

在我的.vim目录中运行它会产生:

4.4M            .
3.6M            ./colors
372.0K          ./plugin
128.0K          ./autoload
100.0K          ./syntax
100.0K          ./doc
Run Code Online (Sandbox Code Playgroud)

(我希望 3.6M 的配色方案不会过多。)

  • 我也有 Perl 答案,但我认为它可能会让人们讨厌我:du -B1 | 排序-nr | perl -e '%h=(0=&gt;b,1=&gt;K,2=&gt;M,3=&gt;G);for(&lt;&gt;){($s,@f)=split/\s+/;$ e=3;$e-- while(1024**$e&gt;$s);$v=($s/(1024**$e));printf "%-8s%s\n",sprintf($ v &gt;= 100 ? "%d%s" : "%.1f%s",$s/(1024**$e),$h{$e}),@f;}' (3认同)

Den*_*son 20

此版本用于awk为排序键创建额外的列。它只调用du一次。输出应该与du.

我已经把它分成多行,但它可以重新组合成一行。

du -h |
  awk '{printf "%s %08.2f\t%s\n", 
    index("KMG", substr($1, length($1))),
    substr($1, 0, length($1)-1), $0}' |
  sort -r | cut -f2,3
Run Code Online (Sandbox Code Playgroud)

解释:

  • BEGIN - 创建一个字符串来索引,用 1、2、3 代替 K、M、G 以按单位分组,如果没有单位(大小小于 1K),则没有匹配项并返回零(完美! )
  • 打印新字段 - 单位、值(为了使 alpha 排序正常工作,它是零填充的、固定长度的)和原始行
  • 索引大小字段的最后一个字符
  • 拉出尺寸的数字部分
  • 对结果进行排序,丢弃多余的列

在没有cut命令的情况下尝试看看它在做什么。

这是一个在 AWK 脚本中进行排序的版本,不需要cut

du -h |
   awk '{idx = sprintf("%s %08.2f %s", 
         index("KMG", substr($1, length($1))),
         substr($1, 0, length($1)-1), $0);
         lines[idx] = $0}
    END {c = asorti(lines, sorted);
         for (i = c; i >= 1; i--)
           print lines[sorted[i]]}'
Run Code Online (Sandbox Code Playgroud)


slm*_*slm 20

这是一个以更紧凑的汇总形式显示目录的示例。它处理目录/文件名中的空格。

% du -s * | sort -rn | cut -f2- | xargs -d "\n" du -sh

53G  projects
21G  Desktop
7.2G VirtualBox VMs
3.7G db
3.3G SparkleShare
2.2G Dropbox
272M apps
47M  incoming
14M  bin
5.7M rpmbuild
68K  vimdir.tgz
Run Code Online (Sandbox Code Playgroud)


小智 16

按大小排序文件(以 MB 为单位)

du --block-size=MiB --max-depth=1 path | sort -n
Run Code Online (Sandbox Code Playgroud)


小智 11

我有一个简单但有用的 python 包装器 du 称为dutop。请注意,我们(coreutils 维护者)正在考虑添加排序功能以直接对“人类”输出进行排序。


0x8*_*x89 11

得到另一个:

$ du -B1 | sort -nr | perl -MNumber::Bytes::Human=format_bytes -F'\t' -lane 'print format_bytes($F[0])."\t".$F[1]'
Run Code Online (Sandbox Code Playgroud)

我开始喜欢 perl。你可能需要做一个

$ cpan Number::Bytes::Human
Run Code Online (Sandbox Code Playgroud)

第一的。致所有的 perl 黑客:是的,我知道排序部分也可以在 perl 中完成。也可能是 du 部分。


Boz*_*joe 10

这段代码是从http://www.unix.com/shell-programming-scripting/32555-du-h-sort.html 的“Jean-Pierre”中无耻地截取的。有什么办法可以更好地信任他吗?

du -k | sort -nr | awk '
     BEGIN {
        split("KB,MB,GB,TB", Units, ",");
     }
     {
        u = 1;
        while ($1 >= 1024) {
           $1 = $1 / 1024;
           u += 1
        }
        $1 = sprintf("%.1f %s", $1, Units[u]);
        print $0;
     }
    '
Run Code Online (Sandbox Code Playgroud)


小智 9

使用“-g”标志

 -g, --general-numeric-sort
              compare according to general numerical value
Run Code Online (Sandbox Code Playgroud)

在我的 /usr/local 目录上产生如下输出:

$ du |sort -g

0   ./lib/site_ruby/1.8/rubygems/digest
20  ./lib/site_ruby/1.8/rubygems/ext
20  ./share/xml
24  ./lib/perl
24  ./share/sgml
44  ./lib/site_ruby/1.8/rubygems/package
44  ./share/mime
52  ./share/icons/hicolor
56  ./share/icons
112 ./share/perl/5.10.0/YAML
132 ./lib/site_ruby/1.8/rubygems/commands
132 ./share/man/man3
136 ./share/man
156 ./share/perl/5.10.0
160 ./share/perl
488 ./share
560 ./lib/site_ruby/1.8/rubygems
604 ./lib/site_ruby/1.8
608 ./lib/site_ruby
Run Code Online (Sandbox Code Playgroud)

  • 但是,这并没有提供人类可读的输出,而这正是 OP 正在寻找的。 (5认同)

Pet*_*unn 7

在网上找到了这个......似乎工作正常

du -sh * | tee /tmp/duout.txt | grep G | sort -rn ; cat /tmp/duout.txt | grep M | sort -rn ; cat /tmp/duout.txt | grep K | sort -rn ; rm /tmp/duout.txt
Run Code Online (Sandbox Code Playgroud)


小智 6

另一个:

du -h | perl -e'
@l{ K, M, G } = ( 1 .. 3 );
print sort {
    ($aa) = $a =~ /(\w)\s+/;
    ($bb) = $b =~ /(\w)\s+/;
    $l{$aa} <=> $l{$bb} || $a <=> $b
  } <>'
Run Code Online (Sandbox Code Playgroud)


mar*_*lar 6

我昨天从编造这个例子中学到了 awk。这花了一些时间,但很有趣,我学会了如何使用 awk。

它只运行 du 一次,它的输出与 du -h 非常相似

du --max-depth=0 -k * | sort -nr | awk '{ if($1>=1024*1024) {size=$1/1024/1024; unit="G"} else if($1>=1024) {size=$1/1024; unit="M"} else {size=$1; unit="K"}; if(size<10) format="%.1f%s"; else format="%.0f%s"; res=sprintf(format,size,unit); printf "%-8s %s\n",res,$2 }'
Run Code Online (Sandbox Code Playgroud)

它以一位小数点显示 10 以下的数字。


Jac*_*obN 6

这是我使用的简单方法,资源使用率非常低,可以满足您的需求:

du --max-depth=1 | sort -n | awk 'BEGIN {OFMT = "%.0f"} {print $1/1024,"MB", $2}'

0 MB ./etc
1 MB ./mail
2 MB ./tmp
123 MB ./public_html
Run Code Online (Sandbox Code Playgroud)


Pat*_*ick 5

du -cka --max-depth=1 /var/log | 排序 -rn | 头-10 | awk '{print ($1)/1024,"MB", $2'}