Назад | Перейти на главную страницу

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

Мне нужно получить список вывода, который может читать человек.

Тем не мение, 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 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)

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

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

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

du -k * | sort -nr | cut -f2 | xargs -d '\n' du -sh

У меня тоже была эта проблема, и в настоящее время я использую обходной путь:

du -scBM | sort -n

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

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

  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

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

Эта версия использует 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 - создать строку для индексации, чтобы заменить 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]]}'

Вот пример, который показывает каталоги в более компактной обобщенной форме. Он обрабатывает пробелы в каталогах / именах файлов.

% 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

сортировать файлы по размеру в МБ

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

Получил еще один:

$ 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. Наверное, ду часть тоже.

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

Этот отрывок был бесстыдно взят из «Жан-Пьера» из 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;
     }
    '

Используйте флаг "-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

Нашел это в сети ... похоже, работает нормально

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 --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

Я изучил awk, придумав вчера этот пример. Это заняло некоторое время, но было очень весело, и я научился использовать awk.

Он запускается только один раз, и его вывод очень похож на 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 с одной десятичной точкой.

Другой:

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

du -cka --max-depth = 1 / var / log | sort -rn | голова -10 | awk '{print (1 доллар США) / 1024, "МБ", 2 доллара США'}

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

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

Дополнительный оператор sed поможет решить проблемы с папками с такими именами, как Application Support.

Вот пример

du -h /folder/subfolder --max-depth=1 | sort -hr

Возврат:

233M    /folder/subfolder
190M    /folder/subfolder/myfolder1
15M     /folder/subfolder/myfolder4
6.4M    /folder/subfolder/myfolder5
4.2M    /folder/subfolder/myfolder3
3.8M    /folder/subfolder/myfolder2

Вы также можете добавить | head -10 чтобы найти первые 10 или любое количество подпапок в указанном каталоге.

Другой 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

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

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

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

du -s * | sort -nr | вырезать -f2 | xargs du -sh

Я использовал решение, предоставленное @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);
}'

http://dev.yorhel.nl/ncdu

команда: ncdu

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

Вуаля:

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

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

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

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

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

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