Как мне отсортировать вывод 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)


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

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

9

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


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 тоже.


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

я думаю, что если это очень большое число, то устройство исчезло, а отображаемое число маленькое ... 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 --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 .
— Трипп Кинетикс

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-глубина = 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 поможет устранить проблемы с папками с такими именами, как поддержка приложений


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


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

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


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

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", а затем преобразовать числа в понятный человеку формат с помощью некоторого сценария или программы.


0

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

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

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


это то, что делает xargs ;-)
— Кадриан

хе-хе, я всегда забываю про xargs. ;) В конце дня, что бы ни делали работу, имхо.

MacOSX по умолчанию (т. Е. За пределами домашнего варки) не поддерживает собственно, xargsпоэтому эта форма была необходима. Однако для файлов с пробелами в них вам нужно установить IFS:IFS=$'\n'
— HankCa

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.