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


我需要获得一个人类可读的du输出列表。

然而, du 没有“按大小排序”选项,并且管道到 sort 不适用于人类可读的标志。

例如,运行:

du | sort -n -r 

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

du |sort -n -r
65108   .
61508   ./dir3
2056    ./dir4
1032    ./dir1
508     ./dir2

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

du -h | sort -n -r

508K    ./dir2
64M     .
61M     ./dir3
2.1M    ./dir4
1.1M    ./dir1

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


830
2018-02-25 13:42




嘿......有趣的你应该问,因为这让我烦恼......至少一年多了。上周我把代码下载到了GNU coreutils(其中有一部分是这个部分),然后看了一下,但是我觉得它需要的时间比我手上要修补的时间要多一些......有人吗? :) - unwind
这是一个很相关的问题: serverfault.com/q/737537/35034 - cregox
你看过这个吗? unix.stackexchange.com/questions/4681/...  它几乎是重复的,值得金。你做得很正常 du 但是将-h添加到 sort 命令。你可以加 -rh 所以最大的是文件中的第一个,否则你需要 tail 看到太空猪。 - SDsolar
当我用Google搜索时,我没想到这样的问题会如此受欢迎。 - Mateen Ulhaq


答案:


作为 GNU coreutils 7.5 2009年8月发布, sort 允许一个 -h 参数,它允许生成的类型的数字后缀 du -h

du -hs * | sort -h

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

brew install coreutils
du -hs * | gsort -h

sort 手册:

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


1152
2017-07-01 12:29



手册的相关部分: gnu.org/software/coreutils/manual/... - wodow
易于在OS X上安装自制软件 - brew install coreutils。 - Richard Poirier
好的!我个人总是这样做 du -BM | sort -nr 作为一种解决方法 - 它是人类可读的,如果有人被旧的coreutils困住,它就会被排序。 - chutz
如果通过Homebrew在OSX上使用,请注意您现在需要使用gsort而不是sort: du -hs * | gsort -h - Brian Cline
@PaulDraper, du -BM 以兆字节为单位打印所有内容,因此168K的文件实际显示为0M。除非存在其他版本差异,否则我不知道。我的版本 du 仅显示整数兆字节值。 - chutz


du | sort -nr | cut -f2- | xargs du -hs

82
2018-02-25 13:52



它会进行大量的重复计数。 - Douglas Leeder
首先它执行正常的du - 然后对于每个条目,它重新计算大小,只是以人类可读的形式打印它。 - Douglas Leeder
@Douglas Leeder:你是正确的重复计数,但认为第二个du不是从冷缓存开始的(感谢操作系统)@hasen j:xargs是一个非常有用的命令,它将它的stdin拆分并作为参数提供到给定的命令 - cadrian
克里斯的实际上是优越的,因为它适用于包含空格的路径。以你的方式投票,伙计。 - rbright
丑,但跨平台:)。 - voretaq7


@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)}<>;'

分成两条线以适合显示器。你可以这样使用它或使它成为单行,它可以任何方式工作。

输出:

4.5M    .
3.7M    ./colors
372K    ./plugin
128K    ./autoload
100K    ./doc
100K    ./syntax

编辑: 经过几轮高尔夫球比赛 PerlMonks,最终结果如下:

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

59
2018-02-25 21:04



您的短版本输出 stderr 因为 die 你可以改变它以使其输出 stdout? - Dennis Williamson
改变 die 到了 print 它会去 stdout。这只是两个字符。 - Adam Bellaire
适用于ubuntu! - marinara
令人印象深刻的perl hackistry - nandoP
结果是以相反的顺序:( - RSFalcon7


我使用了一个非常有用的工具 ncdu 这是为了找到那些讨厌的高磁盘使用文件夹和文件,并删除它们。它基于控制台,快速而轻巧,并且包含所有主要发行版的软件包。


50
2018-02-25 20:39



非常好......如果结果可以用标准输出,我会更有意思...我很懒,我看不懂手册 - ojblass
GT5 是一脉相承的;它的杀手锏正在显示增长。 - Tobu
太棒了!并且比闲逛快得多 du,如果你只想识别大目录。 - BurninLeo


du -k * | sort -nr | cut -f2 | xargs -d '\n' du -sh

43
2018-02-25 14:01



正是我在寻找感谢 - Edward Tanguay
不能用 du -k --total,最后给出错误 du: cannot access 'total': No such file or directory - laggingreflex
我更喜欢这个答案。你怎么去只显示前50个结果呢? - Mauro
@Mauro - 只需将结果传递给 head 通过添加`|最后是-50`头。 - Samuel Lelièvre


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

  1. 改变 du 在显示之前排序。
  2. 改变 sort 支持人体尺寸进行数字排序。
  3. post处理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

20
2018-02-25 13:53





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

du -scBM | sort -n

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


19
2018-02-25 13:56



我喜欢-BM开关,它与-m基本相同,但它具有显示尺寸和M后固定的优点,所以你得到的10M比10只更清晰:) - Tom Feiner
这是我到目前为止在这个页面上看到的最简单的解决方案,谢谢! - Jeff Olson


发现 这个帖子 别处。因此,这个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
}}}'

在我的运行中 .vim 目录产量:

4.4M            .
3.6M            ./colors
372.0K          ./plugin
128.0K          ./autoload
100.0K          ./syntax
100.0K          ./doc

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


18
2018-02-25 14:09



我也有一个Perl的答案,但我认为这可能会让人讨厌我:du -B1 | sort -nr | perl -e'%h =(0 => b,1 => K,2 => M,3 => G);对于(<>){($ s,@ f)= split / \ s + /; $ e = 3; $ e-- while(1024 ** $ e> $ s); $ v =($ s /(1024 ** $ e)); printf“% - 8s%s \ n”,sprintf($ v> = 100?“%d%s”:“%。1f%s”,$ s /(1024 ** $ e),$ h {$ e}),@ f;}' - Adam Bellaire
即使Perl的答案实际上使其格式更接近du。虽然舍入已关闭...看起来du总是给ceil()而不是round() - Adam Bellaire
嘿,为什么我在那里使用哈希?应该是一个阵列......早晨大脑 叽.... - Adam Bellaire
添加了更好的Perl解决方案作为另一个答案。 - Adam Bellaire
当文件名包含空格时,两个版本都会失败 - Vi.


这个版本使用 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

说明:

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

没有的尝试 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]]}'

14
2017-09-04 17:06



谢谢!这是第一个在OS X 10.6中不适用于perl / phython脚本的示例。再次感谢你的好解释。总是很高兴学到新东西。 awk肯定是一个强大的工具。 - Wolf
非常感谢。我改变了杜 du -sh * 只显示没有递归下降的直接文件和目录。 - HankCa