您如何按尺寸对输出进行排序?


196

您如何du -sh /dir/*按大小排序?我读了一个说使用的网站,| sort -n但这显然是不对的。这是一个错误的例子。

[~]# du -sh /var/* | sort -n
0       /var/mail
1.2M    /var/www
1.8M    /var/tmp
1.9G    /var/named
2.9M    /var/run
4.1G    /var/log
8.0K    /var/account
8.0K    /var/crash
8.0K    /var/cvs
8.0K    /var/games
8.0K    /var/local
8.0K    /var/nis
8.0K    /var/opt
8.0K    /var/preserve
8.0K    /var/racoon
12K     /var/aquota.user
12K     /var/portsentry
16K     /var/ftp
16K     /var/quota.user
20K     /var/yp
24K     /var/db
28K     /var/empty
32K     /var/lock
84K     /var/profiles
224M    /var/netenberg
235M    /var/cpanel
245M    /var/cache
620M    /var/lib
748K    /var/spool

3
我知道我曾经看过。该-投票最高的答案有不是很好, 其他人
吉尔斯(Gilles)2010年

接受的答案sort -h于2017年8月在Ubuntu 16.04 LTS中为我工作cd /mnt。然后我做du >~/dumnt.out 然后sort -h ~/dumnt.out >~/dumntsort.out我可以做“ tail〜/ dumntsort.out”以查看最大的太空猪。
SDsolar '17

Answers:


252

如果您拥有GNU coreutils(在大多数Linux发行版中很常见),则可以使用

du -sh -- * | sort -h

-h选项sort表明输入是人类可读的格式(带单位的数字;基于1024;因此1023被认为小于1K,恰好与GNU的匹配du -h)。

该功能已于2009年8月添加到GNU Core Utilities 7.5中

注意:

如果您使用的是Mac OSX的旧版本,则需要使用来安装coreutils brew install coreutils,然后gsort用作的替代产品sort

较新版本的macOS(已在Mojave上验证)sort -h本地支持。


27
注意:-r如果您想在顶部
放大

9
在OSX上,您可以coreutils通过安装brew并将bin文件夹添加PATHrc文件中,并且该文件夹-h应该可用。
kenorb 2015年

哦-谢谢您的-r提醒。这意味着我不需要tail命令来查看猪。
SDsolar

47

尝试使用-k标志来计数使用可读的1K块。这样,您便有了一个通用单位,并且可以轻松地进行数字排序。

du -ck | sort -n

您不需要明确要求人员,但是如果需要,则可以使用多种方法。许多人似乎使用了上面的1K块技术,然后再次调用du。

https://serverfault.com/questions/62411/how-can-i-sort-du-h-output-by-size

如果要查看添加的KB单位,请使用:

du -k | sed -e 's_^\([0-9]*\)_\1 KB_' | sort -n

2
很高兴不必安装其他东西来获得我需要的结果
taranaki

16

如果您没有最新版本的GNU coreutils,则可以调用du-h带来获取可排序的输出,并通过少量的后处理即可生成对人类友好的输出。即使您的版本du没有该-h标志,这也可以正常工作。

du -k | sort -n | awk '
    function human(x) {
        if (x<1000) {return x} else {x/=1024}
        s="kMGTEPZY";
        while (x>=1000 && length(s)>1)
            {x/=1024; s=substr(s,2)}
        return int(x+0.5) substr(s,1,1)
    }
    {gsub(/^[0-9]+/, human($1)); print}'

如果要使用SI后缀(即1000的倍数而不是1024的倍数),请在while循环主体中将1024更改为1000 。(请注意,条件中的预期值为1000,以便获得例如1M而不是1000k。)

如果您du可以选择以字节为单位显示大小(例如-b-B 1-请注意,这可能会对计算实际文件大小而不是磁盘使用量产生副作用),请在ss=" kMGTEPYZ";)的开头添加一个空格,或if (x<1000) {return x} else {x/=1024}在(... 的开头)添加一个空格。该human功能。

读者可以练习在1–10范围内显示十进制数字。


这是我发现在Linux和Mac上均可使用的即用型解决方案。非常感谢!
布莱恩·格雷厄姆

9

如果没有sort -h,可以执行以下操作:

du -sh * | sed 's/\([[:digit:]]\)\t/\1B\t/' | sed 's/\(.\t\)/\t\1/' | sed 's/G\t/Z\t/' | sort -n -k 2d,2 -k 1n,1 | sed 's/Z\t/G\t/'

这将得到du列表,分隔后缀,并使用该列表进行排序。由于没有后缀<1K,因此第一个sed添加一个B(用于字节)。第二个sed在数字和后缀之间添加定界符。第三个sed将G转换为Z,使其大于M;如果有TB文件,则必须将G转换为Y,将T转换为Z。最后,我们按两列进行排序,然后替换G后缀。


很棒的努力,但这并不能为我工作。
jvriesem

6

在OS X上,您可以通过Homebrew安装所需的coreutils :

brew install coreutils

有了它,您将拥有gsort,其中包括-h命令行参数。


4

这个小的Perl脚本可以解决问题。将其另存为duh(或任何您想要的),然后调用duh /dir/*

#!/usr/bin/perl -w
use strict;

my @line;

sub to_human_readable {
        my ($number) = @_;
        my @postfix = qw( k M G T P );
        my $post;
        my $divide = 1;
        foreach (@postfix) {
                $post = $_;
                last if (($number / ($divide * 1024)) < 1);
                $divide = $divide * 1024;
        }
        $number = int($number/$divide + 0.5);
        return $number . $post;
}

sub trimlengthright {
        my ($txt, $len) = @_;
        if ( length($txt) >= $len ) {
                $txt = substr($txt,0,$len - 1) . " ";
        } else {
                $txt = $txt . " " x ($len - length($txt));
        }
        return $txt;
}

sub trimlengthleft {
        my ($txt, $len) = @_;
        if ( length($txt) >= $len ) {
                $txt = substr($txt,0,$len - 1) . " ";
        } else {
                $txt = " " x ($len - length($txt)) . $txt;
        }
        return $txt;
}

open(DF,"du -ks @ARGV | sort -n |");
while (<DF>) {
        @line = split;
        print &trimlengthleft(&to_human_readable($line[0]),5)," "; # size
        print &trimlengthright($line[1],70),"\n"; # directory
}
close DF;

4

因为Mac OS X不具备-h的选项sort,所以我尝试和教训sed,并awk为第一次尝试:

du -sk * | sort -g | awk '{ numBytes = $1 * 1024; numUnits = split("B K M G T P", unit); num = numBytes; iUnit = 0; while(num >= 1024 && iUnit + 1 < numUnits) { num = num / 1024; iUnit++; } $1 = sprintf( ((num == 0) ? "%6d%s " : "%6.1f%s "), num, unit[iUnit + 1]); print $0; }'

这是一条长长的线。展开后,它是:

du -sk * | sort -g | awk '{ 

    numBytes = $1 * 1024; 
    numUnits = split("B K M G T P", unit); 
    num = numBytes; 
    iUnit = 0; 

    while(num >= 1024 && iUnit + 1 < numUnits) { 
        num = num / 1024; 
        iUnit++; 
    } 

    $1 = sprintf( ((num == 0) ? "%6d%s " : "%6.1f%s "), num, unit[iUnit + 1]);
    print $0; 

}'

我在Mac OS X Mavericks,优胜美地,Ubuntu 2014-04上尝试了它,将它awk作为默认值awknawk因为,awk并且都nawk指向/usr/bin/mawk)或gawk,它们都可以工作。

这是Mac上的输出示例:

     0B  bar
     0B  foo
   4.0K  wah
  43.0M  Documents
   1.2G  Music
   2.5G  Desktop
   4.7G  Movies
   5.6G  VirtualBox VMs
   9.0G  Dropbox
  11.7G  Library
  21.2G  Pictures
  27.0G  Downloads

而不是du -sk *,我在@Stefan的答案中看到了还显示了总计,并且没有使用任何遍历任何文件系统挂载点的情况du -skcx *


1

这是我在Ubuntu 10.04,CentOS 5.5,FreeBSD和Mac OS X上使用的东西。

我从www.geekology.co.za/Earthinfo.org借用了这个想法,也从O'Reilly的“ Linux Server Hacks”中臭名昭著的鸭子借来了。我仍在根据自己的需要进行调整。这项工作仍在进行中(例如,今天早上我正在火车上进行这项工作。):

#! /usr/bin/env bash
ducks () {
    du -cks -x | sort -n | while read size fname; do
        for unit in k M G T P E Z Y; do
            if [ $size -lt 1024 ]; then
                echo -e "${size}${unit}\t${fname}"
                break
            fi
            size=$((size/1024))
        done
    done
}
ducks > .ducks && tail .ducks

这是输出:

stefan@darwin:~ $ ducks
32M src
42M .cpan
43M .macports
754M    doc
865M    Work
1G  .Trash
4G  Library
17G Downloads
30G Documents
56G total

stefan@darwin:~ $

我想你的意思是du -cks -x *?(带星号)
nopole 2015年

星号在此用法中是多余的。试试看。
Stefan Lasiewski,2015年

您是说将第一组代码放入一个名为的文件中ducks,然后chmod a+x ducks再用于./ducks运行它吗?然后,我只看到Mac OS X和Ubuntu 2014-10上的总磁盘使用情况。我还尝试将ducks() { ...}定义放进去.bashrc然后用于ducks运行它,在Mac OS X上也是如此,只看到总数
nopole 2015年

1

用这个脚本发疯-

$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;}'

1

在没有GNU的情况下sort -h,这应该可以在大多数UNIX环境中使用:

join -1 2 -2 2 <(du -sk /dir/* 2>/dev/null | sort -k2,2) <(du -sh /dir/* 2>/dev/null | sort -k2,2) | sort -nk2,2 | awk '{ print $3 "\t" $1 }'

0

该文件名使用空格或撇号处理文件名,并且在不支持xargs -d或的系统上工作sort -h

du -s * | sort -n | cut -f2 | tr '\n' '\0' | xargs -0 -I {} du -sh "{}"

结果是:

368K    diskmanagementd
392K    racoon
468K    coreaudiod
472K    securityd
660K    sshd
3.6M    php-fpm

0

这将按照大小的降序对输出进行排序:

du -sh /var/* | sort -k 1rn

这将按照大小的升序对输出进行排序:

du -sh /var/* | sort -k 1n

PS:可用于按任何列排序,但列值应采用相同格式


1
No. sort -k1rn等效于sort -rn并且仅基于每行上十进制数字的初始序列进行数字排序。它不明白浮点,它不理解kMG...后缀。10.1K将超过1.23克被认为是更大
斯特凡Chazelas

0

在Solaris上测试!

du -kh | sort -nk1 | grep [0-9]K && du -kh | sort -nk1 | grep [0-9]M && du -kh | sort -nk1 | grep [0-9]G

这将递归输出所有目录大小,最下面的目录将以千兆字节为单位,最上面的目录以千字节为单位。



0

命令:

du -ah . | sort -k1 -h | tail -n 50

说明:

  • 以可读格式递归列出当前目录中所有文件/文件夹的大小

du -ah .

  • 排序第一列中人类可读的大小,并保留最大的50

sort -k1 -h | tail -n 50


-1

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

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

用户希望获得du -h按数字排序的(人类可读输出)输出。您没有提供答案。您可能还希望将UNIX-SE帐户与其他SE站点上的其他帐户关联。
Tonin

-2

这个脚本更加简单:

for i in G M K; do du -h -d1 / | grep [0-9]$i | sort -n; done

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.