Мне нужно получить список человекочитаемого вывода du.
Однако у 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 сравнивают читаемые человеком числа (например,., 2K 1G)
@Douglas Leeder, еще один ответ: Сортируйте удобочитаемый выход из du-h с помощью другого инструмента. Как Перл!
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][1], конечный результат следующий:
perl -e'%h=map{/.\s/;99**(ord$&&7)-$`,$_}`du -h`;die@h{sort%h}'
[1]: http://www.perlmonks.org/?node_id = 746356
Существует чрезвычайно полезный инструмент под названием ncdu, который предназначен для поиска этих надоедливых папок и файлов с высоким использованием дисков и их удаления. Он консольный, быстрый и легкий, и имеет пакеты для всех основных дистрибутивов.
du -k * | sort -nr | cut -f2 | xargs -d '\n' du -sh
Насколько я понимаю, у вас есть три варианта:
du
для сортировки перед отображением.sort
для поддержки человеческих размеров для числовой сортировки.Вы также можете сделать 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 -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,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
Объяснение:
Попробуйте без команды 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. Вероятно, дю часть тоже.
У меня есть простая, но полезная оболочка для питонов для du под названием dutop. Обратите внимание, что мы (поддерживающие устройства 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 -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 --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.
Он работает только один раз, и у него есть выход, очень похожий на 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 с одной десятичной точкой.