Как мне отсортировать вывод du -h по размеру

968

Мне нужно получить список читабельных выводов.

Однако 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
Вы видели это? unix.stackexchange.com/questions/4681/… Это почти дубликат и стоит золота. Вы делаете нормальный, duно добавляете -h к sortкоманде. Вы можете добавить -rhтак, чтобы самые большие были первыми в файле, в противном случае вам нужно tailувидеть космических свиней.
SDsolar
Я не ожидал, что такой вопрос будет настолько популярным, когда я погуглил это.
Матин Улхак

Ответы:

1365

Начиная с версии GNU coreutils 7.5, выпущенной в августе 2009 года, 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)

ptman
источник
3
Соответствующий раздел руководства: gnu.org/software/coreutils/manual/...
wodow
29
Простота установки на OS X с помощью homebrew - brew install coreutils.
Ричард Пуарье
41
Хороший! Лично я всегда делал du -BM | sort -nrобходной путь - он достаточно читабелен человеком, и он сортируется, если кто-то застрял с более старыми coreutils.
болтовня
30
При использовании на OSX через Homebrew, обратите внимание, что теперь вам нужно использовать gsort, а не sort:du -hs * | gsort -h
Brian Cline
2
@PaulDraper, du -BMпечатает все в мегабайтах, поэтому файл размером 168K будет отображаться как 0M. Если нет какой-то другой версии, о которой я не знаю. Моя версия duпоказывает только целочисленные значения в мегабайтах.
chutz
88
du | sort -nr | cut -f2- | xargs du -hs
cadrian
источник
48
И это сделает огромное количество подсчета дубликатов.
Дуглас Лидер
1
Сначала он делает нормальный du - затем для каждой записи он пересчитывает размер, чтобы просто распечатать его в удобочитаемой форме.
Дуглас Лидер
8
@Douglas Leeder: вы подходите для подсчета дубликатов, но думаете, что второе du не запускается из холодного кэша (благодаря ОС) @hasen j: xargs - очень полезная команда, она разбивает свой stdin и передает его в качестве аргументов данной команде
кадриан
4
Крис на самом деле лучше, так как он работает с путями, содержащими пробелы. Голосуй, приятель.
rbright
3
Гадкий, но кроссплатформенный :).
voretaq7
62

@ Дуглас Лидер, еще один ответ: Сортируйте удобочитаемый вывод 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?
Деннис Уильямсон
2
Измените на diea, printи он перейдет к stdout. Это просто еще два персонажа.
Адам Беллэйр
работает на Ubuntu!
маринара
Впечатляющая perl hackistry
nandoP
Результат в обратном порядке :(
RSFalcon7
55

Существует очень полезный инструмент, который я использую под названием ncdu, который предназначен для поиска этих надоедливых папок и файлов с высоким уровнем использования диска и их удаления. Он консольный, быстрый и легкий, и имеет пакеты для всех основных дистрибутивов.


источник
Очень хорошо ... Мне было бы интересно, если бы результаты можно было вывести на стандартный уровень ... Я так ленив, что не могу прочитать руководство
ojblass
8
gt5 находится в том же духе; его убийственная особенность - рост.
Тобу
1
Это действительно круто! И гораздо быстрее, чем тусоваться du, если вы просто хотите определить большие каталоги.
BurninLeo
44
du -k * | sort -nr | cut -f2 | xargs -d '\n' du -sh
Джейк Уилсон
источник
Не могу использовать с du -k --total, выдает ошибку в концеdu: cannot access 'total': No such file or directory
laggingreflex
Мне нравится этот еще один любой другой ответ. как бы вы показали только первые 50 результатов?
Мау
1
@Mauro - просто передайте результат head, добавив `| голова -50` в конце.
Самуэль Лельевр
21

Насколько я вижу, у вас есть три варианта:

  1. Изменить duсортировку перед отображением.
  2. Изменить sortдля поддержки размеров человека для числовой сортировки.
  3. Выполните обработку вывода из сортировки, чтобы изменить базовый вывод на удобочитаемый.

Вы также можете сделать du -kи жить с размерами в КиБ.

Для варианта 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 :)
Том Фейнер,
Это самое простое решение, которое я видел на этой странице, спасибо!
Джефф Олсон
19

Нашел этот пост в другом месте. Поэтому этот сценарий оболочки будет делать то, что вы хотите, не вызывая 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 цветовых схем не является чрезмерным.)

Адам Беллер
источник
1
У меня тоже есть ответ на Perl, но я думаю, что это может заставить людей ненавидеть меня: du -B1 | сортировать -nr | perl -e '% h = (0 => b, 1 => K, 2 => M, 3 => G); for (<>) {($ 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;} '
Адам Беллэйр
Несмотря на то, что Perl-ответ на самом деле дает его форматирование гораздо ближе к du. Хотя округление выключено ... Похоже, что du всегда дает ceil (), а не round ()
Адам Беллэйр
Эй, почему я использовал хеш там? Должно было быть множество ... утреннее ворчание мозга ...
Адам Беллер
В качестве другого ответа добавлено лучшее решение 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

Объяснение:

  • НАЧАЛО - создать строку для индексации, чтобы заменить 1, 2, 3 на K, M, G для группировки по единицам, если нет единицы (размер меньше 1 КБ), то совпадения нет, и возвращается ноль (отлично! )
  • напечатать новые поля - единицу измерения, значение (для правильной работы альфа-сортировки, с добавлением нуля, фиксированной длины) и исходную строку
  • индексировать последний символ поля размера
  • вытащить числовую часть размера
  • сортировать результаты, отбрасывать лишние столбцы

Попробуйте без 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-scripts. и еще раз спасибо за хорошее объяснение. Всегда приятно узнавать что-то новое. awk уверен, что это мощный инструмент.
Волк,
Большое спасибо за это. Я изменил 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
11

сортировать файлы по размеру в мегабайтах

du --block-size=MiB --max-depth=1 path | sort -n
lukmansh
источник
9

У меня есть простая, но полезная оболочка для Python du, которая называется dutop . Обратите внимание, что мы (сопровождающие coreutils) рассматриваем возможность добавления функциональности для сортировки для прямой сортировки «человеческого» вывода.

pixelbeat
источник
1
+1 за одно из редких, действительных исключений «делай одно и делай это правильно». Если кто-то не разбирается в понимании SI-префикса и / или двоичных префиксов.
Иоахим Зауэр
И, как упоминает Птман ниже: та да ! (новый 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. Вероятно, часть du тоже.

0x89
источник
8

Этот фрагмент был бесстыдно заимствован из «Жан-Пьера» с http://www.unix.com/shell-programming-scripting/32555-du-h-sort.html . Есть ли способ, которым я могу лучше кредитовать его?

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;
     }
    '
Bozojoe
источник
я думаю, что если это очень большое число, то устройство исчезло, а отображаемое число маленькое ... try23423423432423
nopole
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
Это не дает удобочитаемого вывода, однако, это то, что искал ОП.
4

Другой:

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
  } <>'
Димитр Радулов
источник
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
JacobN
источник
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
Peter NUnn
источник
Основываясь на этом однострочнике, я создал скрипт для обеспечения удобочитаемого, отсортированного вывода du (1). Пожалуйста, обратитесь к моему ответу, serverfault.com/a/937459/218692 .
Трипп Кинетикс
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 с одним десятичным знаком.

marlar
источник
3

du -cka --max-глубина = 1 / var / log | сортировать -rn | голова -10 | awk '{print ($ 1) / 1024, "МБ", $ 2'}

Патрик
источник
2

Если вам нужно обрабатывать пробелы, вы можете использовать следующее

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

Дополнительный оператор sed поможет устранить проблемы с папками с такими именами, как поддержка приложений

Chealion
источник
Только что попробовал это на macOS Sierra. Работает как положено. Приятно!
jasonology
1

Вуаля:

du -sk /var/log/* | sort -rn | awk '{print $2}' | xargs -ia du -hs "a"
weeheavy
источник
1

http://dev.yorhel.nl/ncdu

команда: ncdu

Навигация по каталогам, сортировка (имя и размер), графики, удобочитаемые и т. Д.

Адам Эйкхофф
источник
1
Отличная утилита, но не установлена ​​по умолчанию на любой ОС, о которой я знаю. Не обязательно проблема, но еще одна программа, о которой нужно заботиться ...
voretaq7
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
user96753
источник
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Синтаксис BSD поддерживается GNU du с тех пор, как coreutils 8.6 был выпущен в 2010 году (хотя его первая версия Red Hat была RHEL 7 в 2014 году), поэтому вам больше не нужно --maxdepth=1. Я только узнал об этом недавно сам.
Адам Кац
1

ду-с * | сортировать -nr | cut -f2 | xargs du -sh

ageek2remember
источник
Это не очень хорошее решение, потому что оно проходит через файловую систему дважды.
Пол Гир
1

Здесь много ответов, многие из которых являются дубликатами. Я вижу три тенденции: прохождение второго вызова du, использование сложного кода shell / awk и использование других языков.

Вот POSIX-совместимое решение с использованием du и awk, которое должно работать в любой системе.

Я выбрал немного другой подход, добавив, -xчтобы убедиться, что мы остаемся в одной файловой системе (эта операция мне всегда нужна, когда у меня мало места на диске, так зачем отсеивать то, что я смонтировал в этом дереве FS или переместил символьная ссылка назад) и отображение постоянных единиц для облегчения визуального анализа. В этом случае я обычно выбираю не сортировать, чтобы лучше видеть иерархическую структуру.

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

(Так как это в последовательных единицах, вы можете добавить, | sort -nесли вы действительно хотите отсортировать результаты.)

Это отфильтровывает любой каталог, чье (совокупное) содержимое не может превышать 512 МБ, а затем отображает размеры в гигабайтах. По умолчанию, ий использует размер блока 512 байт (так состояние AWK от 2 20 блоков 512 и его- 21 делитель преобразует единицы в ГБ - мы могли бы использовать du -kxс $1 > 512*1024и s/1024^2более читаемым человеком). Внутри условия awk мы устанавливаем sразмер, чтобы мы могли удалить его из строки ( $0). При этом сохраняется разделитель (который свернут в один пробел), поэтому окончательный %sпредставляет пробел, а затем имя агрегированного каталога. %7sвыравнивает округленный %.2fразмер ГБ (увеличьте, %8sесли у вас> 10 ТБ).

В отличие от большинства решений здесь, это правильно поддерживает каталоги с пробелами в их именах (хотя каждое решение, включая это, будет неправильно обрабатывать имена каталогов, содержащие разрывы строк).

Адам Кац
источник
0

По крайней мере, с обычными инструментами это будет сложно из-за формата, в котором читаемые человеком цифры (обратите внимание, что сортировка делает «хорошую работу» здесь, так как сортирует числа - 508, 64, 61, 2, 2 - это просто не могу отсортировать числа с плавающей точкой с дополнительным множителем).

Я бы попробовал все наоборот - использовать вывод из "du | sort -n -r", а затем преобразовать числа в понятный человеку формат с помощью некоторого сценария или программы.

schnaader
источник
0

Что вы можете попробовать это:

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

Надеюсь, это поможет.

Кристиан Виттс
источник
это то, что делает xargs ;-)
Кадриан
хе-хе, я всегда забываю про xargs. ;) В конце дня, что бы ни делали работу, имхо.
MacOSX по умолчанию (т. Е. За пределами домашнего варки) не поддерживает собственно, xargsпоэтому эта форма была необходима. Однако для файлов с пробелами в них вам нужно установить IFS:IFS=$'\n'
HankCa
0
du | sort -nr | awk '{ cmd = "du -h -d0 "$2"| cut -f1"; cmd | getline human; close(cmd); print human"\t"$2 }'
Натан де Врис
источник