Як я можу сортувати du -h вихід за розміром


966

Мені потрібно отримати список людських читабельних результатів.

Однак, 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

Я не очікував, що таке питання буде настільки популярним, коли я переглядаю це.
Mateen Ulhaq

Відповіді:


1360

Станом на 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 з домашньою мовою - варити інсталяцію coreutils.
Річард Поарьє

41
Хороший! Я особисто завжди робив це du -BM | sort -nrяк спосіб вирішення - це достатньо читабельно для людини, і це сортується, якщо хтось застряг із старими основними елементами.
chutz

30
Якщо ви користуєтесь OSX через Homebrew, зверніть увагу, що тепер вам потрібно буде використовувати gsort, а не сортувати:du -hs * | gsort -h
Brian Cline

2
@PaulDraper, du -BMдрукує все в мегабайтах, тому файл розміром 168K насправді відображатиметься як 0М. Якщо є якісь інші розбіжності у версії, про які я не знаю. Моя версія duпоказує лише цілі мегабайтні значення.
chutz

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

48
І це зробить величезну кількість повторних підрахунків.
Дуглас Лідер

1
Спочатку це робиться звичайним способом, а потім для кожного запису він перераховує розмір, щоб просто надрукувати його в читаному для людини вигляді.
Дуглас Лідер

8
@Douglas Leeder: ти маєш право на підрахунок дублікатів, але думай, що друге ду не починається з холодного кешу (завдяки ОС) @hasen j: xargs - дуже корисна команда, вона розбиває свій stdin і подає його як аргументи до даної команди
кадрій

4
Кріс насправді є вищим, оскільки працює з доріжками, що містять пробіли. Кинувши голос, приятель.
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

EDIT: Після кількох раундів гольфу на PerlMonks , остаточний результат такий:

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

2
Ваша коротка версія виходить із- stderrза того, що dieви можете змінити, щоб зробити її вихідною stdout?
Денніс Вільямсон

2
Змініть dieна "a" printі воно перейде до stdout. Це просто ще два персонажі.
Адам Беллер

працює на ubuntu!
Маринара

вражаючий хакерство Perl
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та жити з розмірами в 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

Це не створює масштабованих значень, але завжди створює розмір у мегабайтах. Це менш ідеально, але для мене це краще, ніж нічого (або відображення розміру в байтах).


Мені подобається th -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,6 млн. Кольорових схем не надмірно.)


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;} '
Адам Беллер

Навіть незважаючи на те, що відповідь Perl насправді дає її форматування набагато ближче до du. Хоча округлення вимкнено ... Схоже, дю завжди дає ceil (), а не круглий ()
Адам Беллер

Гей, чому я там використовував хеш? Повинен був бути масив ... ранковий-мозковий бурчання ....
Адам Беллер

Як ще одна відповідь додано краще рішення 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. і ще раз дякую за гарне пояснення. завжди приємно дізнаватися щось нове. 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 слід попередити, що версія mac xargs не підтримує прапор -d, і якщо ви його опустите, у будь-яких каталогах, що містять пробіл, кожне слово окремо розбирається, що, звичайно, не вдається.
jasonology


9

У мене проста, але корисна обгортка python для du під назвою dutop . Зауважте, що ми (сервіси Coreutils) розглядаємо можливість додавання функціональності для сортування безпосередньо "людського" виводу.


1
+1 за одне з рідкісних, дійсних винятків - "робити одну справу і робити все правильно". Якщо хтось не подумає зрозуміти SI-префікс та / або бінарні префікси.
Йоахім Зауер

А як згадує птман нижче: та да ! (новий sortпрапор)
Tobu

9

Отримав ще один:

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

Я починаю любити перл. Можливо, вам доведеться зробити це

$ cpan Number::Bytes::Human

спочатку. Для всіх хакерів Perl там: Так, я знаю, що частину сортування також можна виконати в perl. Напевно, і частина дю.


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

я думаю, якщо це дуже велика кількість, то одиниці немає, а відображене число невелике ... спробуйте23423423432423
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 .
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 - maxx-глибина = 1 / var / log | сортувати -рн | голова -10 | awk '{print ($ 1) / 1024, "MB", $ 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

du -s * | сортувати -nr | вирізати -f2 | xargs du -sh


Це не чудове рішення, оскільки воно обходить файлову систему двічі.
Пол Гір

1

Тут є багато відповідей, багато з яких - це дублікати. Я бачу три тенденції: проходження другого дзвінка, використання складного коду 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 ;-)
cadrian

хе-х, я завжди забуваю про xargs. ;) Зрештою, що завгодно, що робота буде зроблена.

MacOSX за замовчуванням (тобто за межами домашньої заварки) не підтримує належну xargsформу, тому ця форма була необхідною. Однак для файлів з пробілами в них потрібно встановити IFS:IFS=$'\n'
HankCa

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.