Я хотел бы найти самый большой файл в каждом каталоге рекурсивно.

Я хотел бы найти самый большой файл в каждом каталоге рекурсивно.

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

Если возможно, укажите также средний размер файлов в этом каталоге.

Цель состоит в том, чтобы найти в каталогах файлы, которые намного больше других в каталоге, чтобы их можно было заменить.

решение1

В GNU findи sort( sed4.2.2 или выше) выполните сортировку один раз по размерам файлов и еще раз по путям к каталогам:

find /some/dir -type f -printf '%s %f%h\0' | 
  sort -zrn |
  sort -zut/ -k2 |
  sed -zre 's: ([^/]*)(/.*): \2/\1:'

Объяснение:

  • Выводятся размер файла, имя и путь (первый разделяется пробелом, а следующие два разделяются знаком /), и каждая запись завершается символом ASCII NUL.
  • Затем мы сортируем числовым способом, используя размер, предполагая, что вывод разделен NUL (и в обратном порядке, то есть сначала самые большие файлы).
  • Затем мы используем sortдля печати только первые уникальные записи, используя все данные из второго /поля, разделенного символом -, которое будет путем к каталогу, содержащему файл.
  • Затем мы sedменяем местами каталоги и имена файлов, чтобы получить нормальный путь.

Для читаемого вывода замените ASCII NUL на новые строки:

find /some/dir -type f -printf '%s %f%h\0' | 
  sort -zrn |
  sort -zut/ -k2 |
  sed -zre 's: ([^/]*)(/.*): \2/\1:' |
  tr '\0' '\n'

Пример вывода:

$ find /var/log -type f -printf '%s %f%h\0' | sort -zrn | sort -zt/ -uk2 | sed -zre 's: ([^/]*)(/.*): \2/\1:' | tr '\0' '\n'
3090885 /var/log/syslog.1
39789 /var/log/apt/term.log
3968 /var/log/cups/access_log.1
31 /var/log/fsck/checkroot
467020 /var/log/installer/initial-status.gz
44636 /var/log/lightdm/seat0-greeter.log
15149 /var/log/lxd/lxd.log
4932 /var/log/snort/snort.log
3232 /var/log/unattended-upgrades/unattended-upgrades-dpkg.log

решение2

Объединение findи awkпозволяет также рассчитать средние значения:

find . -type f -printf '%s %h/%f\0'|awk 'BEGIN { RS="\0" } { SIZE=$1; for (i = 1; i <= NF - 1; i++) $i = $(i + 1); NF = NF - 1; DIR=$0; gsub("/[^/]+$", "", DIR); FILE=substr($0, length(DIR) + 2); SUMSIZES[DIR] += SIZE; NBFILES[DIR]++; if (SIZE > MAXSIZE[DIR] || !BIGGESTFILE[DIR]) { MAXSIZE[DIR] = SIZE; BIGGESTFILE[DIR] = FILE } }; END { for (DIR in SUMSIZES) { printf "%s: average %f, biggest file %s %d\n", DIR, SUMSIZES[DIR] / NBFILES[DIR], BIGGESTFILE[DIR], MAXSIZE[DIR] } }'

Скрипт AWK, изложенный в более удобном для чтения виде, выглядит следующим образом:

BEGIN { RS="\0" }

{
  SIZE=$1
  for (i = 1; i <= NF - 1; i++) $i = $(i + 1)
  NF = NF - 1
  DIR=$0
  gsub("/[^/]+$", "", DIR)
  FILE=substr($0, length(DIR) + 2)
  SUMSIZES[DIR] += SIZE
  NBFILES[DIR]++
  if (SIZE > MAXSIZE[DIR] || !BIGGESTFILE[DIR]) {
    MAXSIZE[DIR] = SIZE
    BIGGESTFILE[DIR] = FILE
  }
}

END {
  for (DIR in SUMSIZES) {
    printf "%s: average %f, biggest file %s %d\n", DIR, SUMSIZES[DIR] / NBFILES[DIR], BIGGESTFILE[DIR], MAXSIZE[DIR]
  }
}

Это ожидает входные записи, разделенные нулем (я украл это изответ муру); для каждой входной записи это

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

После того, как все это сделано, скрипт перебирает ключи SUMSIZESи выводит каталог, средний размер, имя самого большого файла и его размер.

Вы можете передать вывод в sortсортировку по имени каталога. Если вы хотите дополнительно отформатировать размеры в удобной для человека форме, вы можете изменить строку printfна

printf "%.2f %d %s: %s\n", SUMSIZES[DIR] / NBFILES[DIR], MAXSIZE[DIR], DIR, BIGGESTFILE[DIR]

и затем передать вывод в numfmt --field=1,2 --to=iec. Вы по-прежнему можете сортировать результат по имени каталога, вам просто нужно сортировать, начиная с третьего поля: sort -k3.

решение3

Зш'sшаблоны подстановочных знаковбудет очень полезно для того, что вы делаете. В частности, zsh может сопоставлять файлы по атрибутам, таким как тип, размер и т. д. черезквалификаторы glob. Квалификаторы Glob также позволяют сортировать совпадения.

Например, в zsh *(.DOLN[1])расширяется до имени самого большого файла в текущем каталоге. *— это шаблон для имени файла (соответствует всему, за исключением, возможно, файлов с точкой в ​​зависимости от параметров оболочки). Квалификатор .ограничивает совпадения обычными файлами, Dзаставляет *включать файлы с точкой, OLсортирует по убыванию размера («длины»), Nделает расширение пустым, если нет ни одного соответствующего файла, и [1]выбирает только первое совпадение.

Вы можете перечислять каталоги рекурсивно с помощью **/. Например, следующий цикл рекурсивно перебирает все подкаталоги текущего каталога и их подкаталоги:

for d in **/*(/); do … done

Вы можете использоватьzstatдля доступа к размеру файла и другим метаданным без необходимости использования других инструментов для анализа.

zmodload -F zsh/stat b:zstat
files=(*(DNoL))
zstat -A sizes +size -- $files
total=0; for s in $sizes; do total+=$s; done
if ((#sizes > 0)); then
  max=$sizes[-1]
  average=$((total/#sizes))
  median=$sizes[$((#sizes/2))]
fi

решение4

Попробуйте использовать baobab или что-то похожее, и одно или несколько из них, вероятно, включены в ваш дистрибутив. Они очень хорошо визуализируют проблемные каталоги.

  • Баобаб
  • JDiskReport
  • нкду
  • K4DirStat
  • QDirStat
  • Карта GD

http://alternativeto.net/software/baobab/?platform=linux

А страница руководства baobab рассказывает, как это происходит.

$> man baobab
BAOBAB(1)

NAME
       Baobab - A graphical tool to analyse disk usage

SYNOPSIS
       baobab  [directory]

DESCRIPTION
       baobab is able to scan either specific folders or the whole filesys-
       tem (local and remote), in order to give the user a graphical tree
       representation including each directory size or percentage in the
       branch.  It also auto-detects in real-time any change made to your
       home directory as far as any mounted/unmounted device. A graphical
       treemap window is also provided for any selected folder.

       A detailed documentation on the program could be read at:
       http://www.gnome.org/projects/baobab

AUTHOR
       Fabio MARZOCCA <[email protected]>



                                                                     BAOBAB(1)

Связанный контент