Как отсортировать читабельный размер человека

11

Я в основном ищу файлы, затем сортирую по размеру. Сценарий работает, если я не сортирую размер по удобочитаемому человеку. Но я хочу, чтобы размер был удобочитаемым. Как я могу сортировать размеры, удобочитаемые человеком?

Например:

 ls -l | sort -k 5 -n | awk '{print $9 " " $5}'

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

1.txt 1
test.txt 3
bash.sh* 573
DocGeneration.txt 1131
andres_stuff.txt 1465
Branches.xlsx 15087
foo 23735
bar 60566
2016_stuff.pdf 996850

Теперь я хочу, чтобы размер читался человеком, поэтому я добавил параметр -h в ls, и теперь некоторые файлы вышли из строя:

 ls -lh | sort -k 5 -n | awk '{print $9 " " $5}'
1.txt 1
DocGeneration.txt 1.2K
andres_stuff.txt 1.5K
test.txt 3
Branches.xlsx 15K
foo 24K
bar 60K
bash.sh* 573
2016_stuff.pdf 974K

tvo000
источник
-k 5- как это работает?
Ctrl-Alt-Delor
@ ctrl-alt-delor: я полагаю, что размер находится в 5-м столбце lsвыходных данных
jesse_b
2
Использование duвместо lsможет быть хорошей идеей.
ксеноид
... или find«s -printfс его %pи %sформаттерами ( с последующим„гуманизацией“размеров).
Стивен Китт
@Jessse_b моя ошибка, я просто предположил, что данные в вопросе (помеченные как это то, что я получил) были отсортированным вводом. Я ошибся.
Ctrl-Alt-Delor

Ответы:

28

Пытаться sort -h k2

-h, --human-numeric-sort сравнить числа, читаемые человеком (например, 2K 1G)

Это часть сортировки gnu, BSD и других.

Ctrl-Alt-Делор
источник
5
Разве не lsследует избегать парсинга вывода ?
3
@ Томаш Не всегда. Если он обеспечивает вывод, который вам нужен, передача его в другую операцию форматирования не представляет особой опасности. Чего не следует делать, так это циклически выводить выходные данные lsи вместо этого напрямую использовать глобализацию файлов. Один шарик здесь не подойдет. Тем не менее, я бы предпочел duдля этого.
Bloodgain
1
@Bloodgain Формат ls не обязательно будет одинаковым в бинарных файлах system / ls, поэтому его разбор переносимым считается невозможным.
Д. Бен Кнобл
1
Кроме того, имена файлов с пробелами будут портить вещи
Д. Бен Нобл
1
@Bloodgain: files=(); for f in *; do [[ -L "$f" ]] && files+=("$f"); done; echo ${#files[@]}(я могу ошибаться при переключении тестовых символов ). Если вас не интересуют символические ссылки, files=(*); echo ${#files[@]}которые становятся переносимыми, если вы используете, setа не массивы.
Д. Бен Кнобл,
29

lsимеет встроенную функциональность, используйте -Sопцию и сортируйте в обратном порядке:ls -lShr

       -r, --reverse
              reverse order while sorting

       -S     sort by file size, largest first
Марк Маккинстри
источник
1
-hне является стандартным lsвариантом , но должен использоваться, если OP уже имеет его. Остальные стандартные, и это, конечно, ответ, который я бы написал.
Тоби Спейт
5
+1 Не балуйтесь, разбирая вывод ls.
Дэвид Ричерби
Это лучший ответ, но он должен включать информацию в комментарии @ Toby: -Sможет быть недоступно для вас ls. FWIW -Sподдерживается даже библиотекой Emacs ls-lisp.el, которая используется, когда ОС не имеет ls. Это работает в Emacs на MS Windows, например.
Дрю
Это должен быть принятый ответ.
разброс
1
@Drew: Комментарий Тоби говорит, что он -hне может быть универсально доступен, но OP уже использует его в любом случае. -Sдействительно должен быть общедоступным, потому что он находится в ссылке POSIX, которую предоставляет Тоби. Тем не менее, существует довольно много наборов инструментов, отличных от POSIX.
Кевин
5

Поскольку никакой конкретной оболочки не было упомянуто, вот как все это сделать в zshоболочке:

ls -lhf **/*(.Lk-1024oL)

**Модель Глоба соответствует как , *но через /в имени пути, то есть как бы рекурсивный поиск.

Команда lsвключила бы удобочитаемые размеры с -h, и длинный формат вывода списка с -l. В -fопции отключает сортировку, так lsпросто список файлов , в том порядке , они получают.

Этот порядок упорядочен по **/*(.Lk-1024oL)шаблону подстановки имени файла, так что меньшие файлы перечислены первыми. **/*Бит соответствует каждый файл и каталог в этом каталоге и ниже, но (...)модифицирует поведение Глоб ( в это «Глоб классификатор»).

В oLконце упорядочивает ( o) имена по размеру файла ( L"длина").

В .начале заставляет глобус соответствовать только обычным файлам (без каталогов).

В Lk-1024бит выбирает файлы, размер которых составляет менее 1024 Кб ( «длина в КБ менее чем 1024»).

Если zshне ваша основная интерактивная оболочка, то вы можете использовать

zsh -c 'ls -lf **/*(.Lk-1024oL)'

Используйте setopt GLOB_DOTS(или zsh -o GLOB_DOTS -c ...) также для сопоставления скрытых имен. ... или просто добавить Dк строке квалификатора glob.


Расширяя вышесказанное, предполагая, что вы хотите вывод в 2 столбца с именами путей и удобочитаемыми размерами, а также предполагая, что вы используете numfmtGNU coreutils,

zmodload -F zsh/stat b:zstat

for pathname in **/*(.Lk-1024oL); do
    printf '%s\t%s\n' "$pathname" "$(zstat +size "$pathname" | numfmt --to=iec)"
done

или, быстрее,

paste <( printf '%s\n' **/*(.Lk-1024oL) ) \
      <( zstat -N +size **/*(.Lk-1024oL) | numfmt --to=iec )
Кусалананда
источник
4

Если у вас sortнет -hопции, вы можете использовать (хотя и очень длинную) команду awk, как показано ниже:

find . -type f -size -1024k -exec ls -al {} \; | sort -k 5 -n | awk '{if ($5 > 1099511627776) {print $9,$5/1024/1024/1024/1024"T"} else if ($5 > 1073741824) {print $9,$5/1024/1024/1024"G"} else if ($5 > 1048576) {print $9,$5/1024/1024"M"} else if ($5 > 1024) {print $9,$5/1024"K"} else {print $9,$5"B"}}' | column -t

Это отсортирует ваши выходные данные в байтах, а затем преобразует их в их удобочитаемый размер.

jesse_b
источник
-1

Будет ли это работать?

ls -l | awk '{if ($5<=1024) {print}}' | sort -k 5 -n | awk '{print $9"\t"substr($5/1024,1,3)"k"} '| column -t

Первый awkexp будет искать файлы размером менее 1M, а второй возьмет из результата размер в байтах, преобразует его в КБ и напечатает первые 3 элемента, чтобы получить читабельный размер.

Виньеш С.П.
источник
Это на самом деле не решает вопрос OPS - он только смотрит в текущий каталог и печатает только обычные файлы. Также будет сравниваться с 1 КБ вместо 1 МБ. Наконец, мы ищем ответы с некоторыми объяснениями того, почему код работает.
Grochmal
Мой плохой добавил, что он делает.
Виньеш С.П.