it-swarm.xyz

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

1029
Tom Feiner

Начиная с 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)

1444
ptman
du | sort -nr | cut -f2- | xargs du -hs
89
cadrian

@ Дуглас Лидер, еще один ответ: Сортируйте удобочитаемый вывод от 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`;[email protected]{sort%h}'
62
Adam Bellaire

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

57
neutral
du -k * | sort -nr | cut -f2 | xargs -d '\n' du -sh
44
chrisharris.

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

  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
21
Douglas Leeder

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

du -scBM | sort -n

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

20
Joachim Sauer

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

19
Adam Bellaire

Эта версия использует 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]]}'
15
Paused until further notice.

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

% 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
15
slm

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

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

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

9
pixelbeat

Есть еще один:

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

9
0x89

Этот фрагмент был бесстыдно заимствован из "Жан-Пьера" из 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;
     }
    '
8
Bozojoe

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

Нашел этот на линии ... кажется, работает нормально

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
5
Peter Nunn

Вот простой метод, который я использую, очень низкое использование ресурсов и дает вам то, что вам нужно:

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
JacobN

Я узнал 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 с одним десятичным знаком.

4
marlar

Другой:

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

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

3
Patrick

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

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

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

2
Chealion

Вуаля:

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

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

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

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

1
Adam Katz

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

http://dev.yorhel.nl/ncd

команда: ncdu

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

1
Adam Eickhoff

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

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

1
ageek2remember

Вот пример

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 или любое количество подпапок в указанном каталоге.

1
ode2k

Это псевдоним, который я имею в .profile

псевдоним du = 'Sudo du -xh --max-глубина = 1 | сортировать

сортировка -h это то, что действительно помогает здесь на вопрос.

Другие полезные опции - du -x, чтобы остаться в той же файловой системе; Также Sudo помогает не видеть ошибок, если есть каталоги, которые не доступны для чтения всем пользователям. Кроме того, я всегда делаю du --max-deep = 1, затем углубляюсь и т.д.

0
Tagar

Еще один сценарий du!

Поскольку уже есть много ответов, я просто публикую свой собственный сценарий там. Я использую с более чем восьми лет.

Это может быть запущено

/somepath/rdu.sh [-b] [/somepath] [minSize]

где

  • необязательный флаг -b указать использовать количество байтов вместо количество блоков
  • необязательный путь в качестве 1-го аргумента, текущий каталог по умолчанию.
  • если второй аргумент не указан, минимальный размер для печати равен 256Mb.

Вывод может выглядеть так:

\___   3.01G                 21.67%                .cache
|   \___   1.37G                 45.54%                mozilla
|   |   \___   1.37G                100.00%                firefox
|   |   |   \___ 581.71M                 41.48%                billiethek.default
|   |   |   |   \___ 522.64M                 89.85%                cache2
|   |   |   |   |   \___ 522.45M                 99.96%                entries
...

Есть скрипт:

#!/bin/bash

if [ "$1" == "-b" ] ;then
    shift
    units=(b K M G T P)
    duargs="-xbs"
    minsize=${2:-$((256*1024**2))}
else
    units=(K M G T P)
    duargs="-xks"
    minsize=${2:-$((256*1024))}
fi

humansize() {
    local _c=$1 _i=0
    while [ ${#_c} -gt 3 ] ;do
        ((_i++))
        _c=$((_c>>10))
    done
    _c=$(( ( $1*1000 ) >> ( 10*_i ) ))
    printf ${2+-v} $2 "%.2f%s" ${_c:0:${#_c}-3}.${_c:${#_c}-3} ${units[_i]}
}
percent() {
    local p=000$((${1}00000/$2))
    printf ${3+-v} $3 "%.2f%%" ${p:0:${#p}-3}.${p:${#p}-3}
}

device=$(stat -c %d "${1:-.}")
printf -v sep "%16s" ""

rdu() {
    local _dir="$1" _spc="$2" _crt _siz _str _tot _pct
    while read _siz _crt;do
        if [ "$_crt" = "total"  ]; then
            _tot=$_siz
        else
            [ "$_tot" ] || _tot=$_siz
            if [ $_siz -gt $minsize ];then
                humansize $_siz _str
                percent $_siz $_tot _pct
                printf "%s\___ %7s%s%7s%s%s\n" \
                    "$_spc" $_str "$sep" $_pct "$sep" "${_crt##*/}"
                [ -d "$_crt" ] &&
                [ $(stat -c %d "$_crt") -eq $device ] &&
                rdu "$_crt" "|   $_spc"
            fi
        fi
    done < <(
        find "$_dir" -mindepth 1 -maxdepth 1 -xdev \
            \( -type f -o -type d \) -printf "%D;%p\n" |
            sed -ne "s/^${device};//p" |
            tr \\n \\0 |
            xargs -0 du ${duargs}c |
            sort -nr
    )
}

rdu "${1:-.}"

И нет, я не буду публиковать их на Git***.xxx.

Вы можете показать их там или скачать скрипт там.

0
F. Hauri

Вот мое решение, простой bash-скрипт, который вызывает du только один раз и показывает вам только каталоги размером 1 МБ или больше:

#!/bin/env bash
# Usage: my_du.sh [subdirectory levels]
#   For efficiency, only calls "du" once, and stores results in a temp file
#   Stephen Becker, 2/23/2010

if [ $# -gt 0 ]; then
# You may prefer, as I do, to just summarize the contents of a directory
# and not view the size of its subdirectories, so use this:
    du -h --max-depth $1 > temp_du_file
else
    du -h > temp_du_file
fi


# Show all directories of size > 1 GB:
cat temp_du_file | grep "^\([0-9]\|\.\)\+G" | sort -nr
# Show all directories of size > 1 MB:
cat temp_du_file | grep "^\([0-9]\|\.\)\+M" | sort -nr

rm temp_du_file
0
Stephen

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

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

0
schnaader

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

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

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

0
Christian Witts
du | sort -nr | awk '{ cmd = "du -h -d0 "$2"| cut -f1"; cmd | getline human; close(cmd); print human"\t"$2 }'
0
Nathan de Vries

Следующее решение похоже на оригинал cadrian, однако оно будет запускать только две команды du, а не одну du для каждого каталога в дереве.

du -hs `du |sort -g |cut -f2- `

Однако решение Кардриана является более надежным, поскольку вышеприведенное не будет работать для очень густонаселенных деревьев, так как оно может превысить ограничение на размер аргументов, передаваемых du

0
Steve Weet

Основываясь на логике в этот однострочный , я написал скрипт, который предоставляет отсортированный читаемый человеком вывод du (1). Кроме того, что требуется -h флаг для удобочитаемости, он не требует никаких других не POSIX-совместимых команд.

Он доступен по адресу https://github.com/pleappleappleap/sorted-human-d .

0
Tripp Kinetics

Почему бы не бросить еще одну шляпу в кольцо ... это старый вопрос, но вот пример, который (в основном) представляет собой чистый сценарий Shell (fwiw) - то есть, просто bash, а не Perl/python/awk/и т.д. Так что в этом смысле, может быть, он предлагает что-то новое для обсуждения (или нет). Он рассчитывает размер файла только один раз, но печатает в различных единицах (мои предпочтения). (Неупрощенная версия включает в себя getopts, который исключает "ГБ", если это нежелательно.)

#!/bin/bash

printf -- ' %9s %9s %9s       %-30s\n' 'K'        'M'        'G'        'Path'
printf -- ' %9s %9s %9s       %-30s\n' '--------' '--------' '--------' '-----------'
du -sk "[email protected]" | while read val; do
    file=$(echo "$val" | cut -f2-)
    size_k=$(echo "$val"  | cut -f1)
    printf ' %9s %9s %9s       %-30s\n' \
          ${size_k}  \
          $(( size_k / 1024 ))  \
          $(( size_k / 1024 / 1024 ))  \
          "$file"
  done | sort -n
0
michael

Сортировка по убыванию.

du -s ./* | sort -n| cut -f 2-| xargs du -sh {}
0
Peter Nduati