Как я могу сортировать 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
по размеру?
30 ответов
По состоянию на 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
@ Дуглас Ледер, еще один ответ: Сортируйте удобочитаемый результат с 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`;[email protected]{sort%h}'
Существует очень полезный инструмент, который я называю ncdu , который предназначен для поиска того, что надоедливый высокий диск -опасные папки и файлы и их удаление. Он основан на консоли, быстрый и легкий, и имеет пакеты на всех основных дистрибутивах.
Насколько я вижу, у вас есть три варианта:
- Изменить
du
для сортировки перед отображением. - Изменить
sort
для поддержки размеров людей для численного сортирования. - Постовать процесс вывода из сортировки, чтобы изменить основной вывод на понятный для человека.
Вы также можете сделать 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
У меня тоже была эта проблема, и в настоящее время я использую обходной путь:
du -scBM | sort -n
Это не приведет к масштабированным значениям, но всегда будет иметь размер в мегабайтах. Это не так идеально, но для меня это лучше, чем ничего (или отображение размера в байтах).
Найдено это сообщение в другом месте. Поэтому этот сценарий оболочки будет делать то, что вы хотите, не вызывая 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 цветовых схем не является чрезмерным.)
В этой версии используется 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 для группировки по единицам, если нет единицы (размер меньше 1K), тогда нет совпадения и возвращается нуль (отлично!)
- напечатайте новые поля - unit, value (чтобы обработка альфа-сортировки работала правильно, она была заполнена нулями, фиксированная длина) и оригинальной линией
- индекс последнего символа поля размера
- вытащите цифровую часть размера
- сортировать результаты, отбрасывать дополнительные столбцы
Попробуйте без команды 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
У меня простая, но полезная оболочка python для du, называемая dutop . Обратите внимание, что мы (разработчики coreutils) рассматриваем возможность добавления функциональности сортировки для сортировки «человеческого» вывода напрямую.
Получается другое:
$ 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. Вероятно, и эта часть тоже.
сортировать файлы по размеру в MB
du --block-size=MiB --max-depth=1 path | sort -n
Используйте флаг «-g»
-g, --general-numeric-sort
compare according to general numerical value
И в моем /usr /локальном каталоге выводятся следующие данные:
$ 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
Этот фрагмент был бесстыдным зацепился от «Жан-Пьера» из 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;
}
'
Другой:
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 -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
Я научился 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 --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
du -cka --max-depth = 1 /var /log | sort -rn | head -10 | awk '{print ($ 1) /1024, "MB", $ 2'}
Если вам нужно обрабатывать пробелы, вы можете использовать следующие
du -d 1| sort -nr | cut -f2 | sed 's/ /\\ /g' | xargs du -sh
Дополнительная команда sed поможет устранить проблемы с папками с такими именами, как поддержка приложений
вуаля:
du -sk /var/log/* | sort -rn | awk '{print $2}' | xargs -ia du -hs "a"
Команда: ncdu
Навигационная навигация по каталогам, сортировка (имя и размер), графическое оформление, считывание человеком и т. д.
Другое решение 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
Я использовал решение, предоставленное @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);
}'
Здесь много ответов, многие из которых являются дубликатами. Я вижу три направления: прохождение второго звонка, использование сложного кода оболочки /awk и использование других языков.
Вот POSIX-совместимое решение , используя du и awk , которые должны работать на каждой системе.
Я сделал несколько иной подход, добавив -x
, чтобы мы оставались в одной и той же файловой системе (мне нужна эта операция, когда мне не хватает места на диске, поэтому зачем вырывать вещи, которые я смонтировал в этом дереве FS или перемещался и был привязан назад?) и отображал постоянные единицы, чтобы упростить визуальный синтаксический анализ. В этом случае я обычно выбираю not для сортировки, чтобы лучше видеть иерархическую структуру.
sudo du -x | awk '
$1 > 2^20 { s=$1; $1=""; printf "%7sG%s\n", sprintf("%.2f",s/2^21), $0 }'
(Так как это в последовательных единицах, вы можете добавить | sort -n
, если вы действительно хотите sort ed results.)
Отфильтровывает любой каталог, чей (кумулятивный) контент не может превышать 512 МБ, а затем отображает размеры в гигабайтах. По умолчанию du использует размер блока размером в 512 байт (поэтому условие awk для блоков 2 20 составляет 512 МБ, а его делитель 2 21 преобразует единицы в GB - мы могли бы используйте du -kx
с $1 > 512*1024
и s/1024^2
, чтобы быть более удобочитаемым для человека). Внутри awk-условия мы устанавливаем s
размер, чтобы мы могли удалить его из строки ($0
). Это сохраняет разделитель (который сворачивается в одно пространство), поэтому последний %s
представляет пробел, а затем имя агрегированного каталога. %7s
выравнивает размер округленного %.2f
GB (увеличивается до %8s
, если у вас есть> 10TB).
В отличие от большинства решений здесь это правильно поддерживает каталоги с пробелами в именах (хотя решение every , в том числе и это, приведет к неправильному использованию имен каталогов, содержащих разрывы строк) .
По крайней мере, с обычными инструментами это будет сложно из-за формата, в котором читаются человеческие числа (обратите внимание, что сортировка делает «хорошую работу» здесь, поскольку сортирует числа - 508, 64, 61, 2, 2 - он просто не может сортировать числа с плавающей запятой с дополнительным множителем).
Я бы попробовал это наоборот: используйте вывод «du | sort -n -r», а затем преобразуйте числа в удобочитаемый формат с помощью какого-либо скрипта или программы.
Что вы можете попробовать:
for i in `du -s * | sort -n | cut -f2`
do
du -h $i;
done
Надеюсь, что это поможет.
du | sort -nr | awk '{ cmd = "du -h -d0 "$2"| cut -f1"; cmd | getline human; close(cmd); print human"\t"$2 }'
Следующее решение похоже на оригинал cadrian, но в этом случае будут выполняться только две команды du, а не один du для каждой директории в дереве.
du -hs `du |sort -g |cut -f2- `
Однако решение Кардриана более надежное, поскольку вышеприведенное не будет работать для очень густонаселенных деревьев, поскольку оно может превышать предел размера аргументов, переданных du