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


966

我需要获取人类可读的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 按大小排序的方法吗?


嘿...您应该问这个有趣,因为这已经使我烦恼了……至少一年多了。上周,我将代码下载到了GNU coreutils(属于其中一部分),并进行了查看,但决定花很多时间来修补补丁……有人吗?:)
放松

这是一个非常相关的问题:serverfault.com/q/737537/35034
cregox 2015年

你看过这个吗? unix.stackexchange.com/questions/4681/… 它几乎是重复的,值得金。您执行常规操作,du但将-h添加到sort命令中。您可以添加-rh最大的文件,tail使其位于文件的第一位,否则您需要查看太空猪。
SDsolar

我没想到当我用谷歌搜索这个问题时会如此受欢迎。
Mateen Ulhaq,

Answers:


1360

从2009年8月发布的GNU coreutils 7.5开始,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)


3
本手册的相关章节:gnu.org/software/coreutils/manual/...
wodow

29
易于使用自制软件在OS X上安装-brew install coreutils。
理查德·波里耶

41
好一个!我个人总是将其du -BM | sort -nr作为一种解决方法-如果有人被旧的coreutils所困扰,它就足以被人阅读,并且可以进行排序。
chutz'5

30
如果通过Homebrew在OSX上使用,请注意,您现在需要使用gsort而不是sort:du -hs * | gsort -h
Brian Cline

2
@PaulDraper,du -BM以兆字节为单位打印所有内容,因此168K的文件实际显示为0M。除非存在其他版本差异,否则我不知道。我的版本du仅显示整数兆字节值。
chutz 2014年

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

48
并且它将进行大量重复计数。
道格拉斯·里德

1
首先,它会执行正常的du-然后,对于每个条目,它都会重新计算尺寸,只是以人类可读的形式打印出来。
道格拉斯·里德

8
@Douglas Leeder:您应该进行重复计数,但是认为第二个du并不是从冷缓存开始的(感谢OS)@hasen j:xargs是一个非常有用的命令,它拆分其stdin并将其作为参数输入给定命令
cadrian

4
Chris的优势实际上是优越的,因为它可以处理包含空格的路径。兄弟们,以自己的方式投票。
rbright

3
丑陋,但跨平台:)。
voretaq7

62

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

2
您的简短版本会输出,stderr因为die您可以更改它以使其输出stdout
丹尼斯·威廉姆森2009年

2
将更die改为print,它将转到stdout。这只是两个字符。
亚当·贝莱尔

在ubuntu上工作!
marinara '04 -4-26

令人印象深刻的perl hackistry
nandoP 2013年

结果是相反的顺序:(
RSFalcon7

55

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


很好...如果结果可以按标准输出,我会感到很满意...我很懒惰,无法阅读手册
ojblass

8
gt5是同一脉络;它的杀手级功能正在显示增长。
东武

1
太棒了!du如果您只想识别大型目录,则比使用挂起要快得多。
BurninLeo


21

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

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

您也可以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

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

du -scBM | sort -n

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


我喜欢-BM开关,它与-m基本相同,但是它具有显示大小和后缀M的优点,因此您得到的10M比10清晰得多:)
Tom Feiner

这是我到目前为止在此页面上看到的最简单的解决方案,谢谢!
杰夫·奥尔森

19

其他地方找到此帖子。因此,此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

(我希望360万种配色不会过多。)


1
我也有Perl的答案,但我认为这可能会让人们讨厌我:du -B1 | 排序-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 2009年

嘿,我为什么在那里使用哈希?应该是一个数组...早脑发牢骚 ....
Adam Bellaire

添加了更好的Perl解决方案作为另一个答案。
亚当·贝莱尔

当文件名包含空格时,这两个版本都会失败
Vi。

15

此版本用于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-创建一个字符串索引以用K,M,G替换1,2,3来按单位分组,如果没有单位(大小小于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]]}'

谢谢!这是在OS X 10.6中不对perl / phython脚本进行计数的第一个对我有效的示例。再次感谢您的良好解释。总是很高兴学习新东西。肯定是一个强大的工具。

对此非常感谢。我将du更改du -sh *为仅显示立即文件和目录,而没有递归下降。
HankCa

15

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

% 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

1
警告macOS / OSX用户,xargs的Mac版本不支持-d标志,如果省略它,则任何包含空格的目录都将分别解析每个单词,这当然会失败。
jasonology's

11

按大小(MB)对文件排序

du --block-size=MiB --max-depth=1 path | sort -n

9

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


1
+1是一种罕见的有效例外,可以“做一件事情并正确地做到这一点”。除非有人能够理解SI前缀和/或二进制前缀。
约阿希姆·绍尔

正如ptman在下面提到的:ta da!(新sort国旗)
东武

9

还有另一个:

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

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

$ cpan Number::Bytes::Human

第一。对于所有perl黑客:是的,我知道排序部分也可以在perl中完成。大概也是。


8

该片段是从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;
     }
    '

我认为如果这是一个非常大的数字,则该设备不见了,显示的数字很小...试试23423423432423
nopole 2015年

7

使用“ -g”标志

 -g, --general-numeric-sort
              compare according to general numerical value

并且在我的/ 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

4
但是,这并没有提供人类可读的输出,而这正是OP所寻找的。


4

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

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

4

在网上找到了这个……似乎行得通

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

基于这种单行代码,我松散地创建了一个脚本,用于提供人类可读的,排序的du(1)输出。请参考我的答案serverfault.com/a/937459/218692
Tripp Kinetics

3

我昨天从构想这个例子中学到了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 }'

它显示低于10的数字,带有一个小数点。


3

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


2

如果需要处理空格,可以使用以下命令

 du -d 1| sort -nr | cut -f2 | sed 's/ /\\ /g' | xargs du -sh

附加的sed语句将有助于减轻诸如Application Support之类名称的文件夹的问题


刚刚在macOS Sierra上尝试过。可以正常工作。真好!
jasonology's

1

Voilà:

du -sk /var/log/* | sort -rn | awk '{print $2}' | xargs -ia du -hs "a"


1

另一个awk解决方案-

du -k ./* | sort -nr | 
awk '
{split("KB,MB,GB",size,",");}
{x = 1;while ($1 >= 1024) 
{$1 = $1 / 1024;x = x + 1} $1 = sprintf("%-4.2f%s", $1, size[x]); print $0;}'


[jaypal~/Desktop/Reference]$ du -k ./* | sort -nr | awk '{split("KB,MB,GB",size,",");}{x = 1;while ($1 >= 1024) {$1 = $1 / 1024;x = x + 1} $1 = sprintf("%-4.2f%s", $1, size[x]); print $0;}'
15.92MB ./Personal
13.82MB ./Personal/Docs
2.35MB ./Work Docs
1.59MB ./Work Docs/Work
1.46MB ./Personal/Raa
584.00KB ./scan 1.pdf
544.00KB ./Personal/Resume
44.00KB ./Membership.xlsx
16.00KB ./Membership Transmittal Template.xlsx

1

我一直在使用@ptman提供的解决方案,但是最近的服务器更改使其不再可行。相反,我使用以下bash脚本:

#!/bin/bash
# File: duf.sh
# list contents of the current directory by increasing 
#+size in human readable format

# for some, "-d 1" will be "--maxdepth=1"
du -k -d 1 | sort -g | awk '
{
if($1<1024)
    printf("%.0f KB\t%s",$1,$2);
else if($1<1024*1024)
    printf("%.1f MB\t%s",$1/1024,$2);
else
    printf("%.1f GB\t%s",$1/1024/1024,$2);
}'

du -d 1自从coreutils 8.6在2010年发布以来,GNU du就一直支持BSD 语法(尽管它的第一个Red Hat可用性是2014年的RHEL 7),所以您不再需要--maxdepth=1。我最近才才发现这一点。
亚当·卡兹


1

这里有很多答案,很多都是重复的。我看到了三种趋势:通过第二个du调用进行管道传输,使用复杂的shell / awk代码以及使用其他语言。

这是一个使用duawkPOSIX兼容解决方案,该解决方案适用于每个系统。

我采用了略有不同的方法,-x以确保我们保持在同一文件系统上(我仅在磁盘空间不足时才需要执行此操作,所以为什么要清除我已安装在此FS树内或移动并符号链接返回?)并显示常量单位,以便于进行视觉解析。在这种情况下,我通常选择排序,以便更好地了解层次结构。

sudo du -x | awk '
  $1 > 2^20 { s=$1; $1=""; printf "%7sG%s\n", sprintf("%.2f",s/2^21), $0 }'

(由于这是一致的单位,因此,| sort -n如果您确实要结果进行排序,则可以追加。)

这将筛选出(累积)内容超过512MB的所有目录,然后以GB为单位显示大小。默认情况下,杜使用512字节的块大小(因此的2 AWK的病情20块为512MB和其2 21除数单位转换为GB -我们可以使用du -kx$1 > 512*1024s/1024^2更人类可读的)。在awk条件内,我们将其设置s为大小,以便可以将其从行($0)中删除。这将保留定界符(将其折叠到一个空格中),因此最终名称%s代表一个空格,然后代表聚合目录的名称。 %7s对齐舍入的%.2fGB大小(%8s如果大于10TB ,则增加)。

与此处的大多数解决方案不同,此解决方案可以正确支持名称中带有空格的目录(尽管每个解决方案(包括该解决方案都会对包含换行符的目录名称进行错误处理))。


0

至少对于普通工具而言,这将是困难的,因为人类可读的数字所采用的格式(请注意,sort在对数字进行排序时做得很好,因为它对数字进行排序-508、64、61、2、2-只是无法使用额外的乘数对浮点数进行排序)。

我会尝试另一种方法-使用“ du | sort -n -r”的输出,然后使用一些脚本或程序将数字转换为人类可读的格式。


0

您可以尝试的是:

for i in `du -s * | sort -n | cut -f2`
do
  du -h $i;
done

希望能有所帮助。


这就是xargs所做的;-)
cadrian

呵呵,我总是忘了xargs。;)归根结底,无论完成什么工作,imo都是如此。

默认情况下,MacOSX(即自制软件之外)不支持适当的xargs格式,因此此格式是必需的。但是,对于其中包含空格的文件,您需要设置IFS:IFS=$'\n'
HankCa '16

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.