Найдите подпапки, занимающие много места на диске

Мне бы хотелось написать сценарий bash, который поможет мне найти возможности сокращения использования диска.

Скрипт принимает 2 аргумента: родительскую папку (у меня это обычно /apps/) и порог (например, «200M»).

Мой текущий подход не идеален (не использует порог и показывает много избыточного вывода).

В настоящее время я запускаю cd /apps/ && du -aBM 2>/dev/null | sort -nr | head -n 15 и вижу вывод вроде:

8975M   .
1448M   ./delta
1387M   ./alpha
1350M   ./alpha/releases
1144M   ./bravo/releases
1144M   ./bravo
1137M   ./charlie
1117M   ./delta/releases
902M    ./alpha/releases/202210091311
871M    ./charlie/releases
796M    ./echo
794M    ./echo/releases
791M    ./alpha/releases/202210091311/node_modules
703M    ./scoreboard
684M    ./scoreboard/node_modules

Я бы хотел, чтобы в выводе были пропущены такие строки, как:

8975M   .
1448M   ./delta
1387M   ./alpha
1350M   ./alpha/releases
1144M   ./bravo
1137M   ./charlie
902M    ./alpha/releases/202210091311
796M    ./echo
703M    ./scoreboard

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

Вот наиболее интересные строки:

1144M   ./bravo/releases
1117M   ./delta/releases
871M    ./charlie/releases
794M    ./echo/releases
791M    ./alpha/releases/202210091311/node_modules
684M    ./scoreboard/node_modules

Однако я не думаю, что подход du -aBM 2>/dev/null | sort -nr — правильная отправная точка для достижения моей реальной цели.

Потому что на самом деле, возможно, любая из этих папок (в моем последнем примере) даже не настолько вложена/глубока, как могла бы быть (подпапки самого низкого уровня, которые также удовлетворяют порогу в 200 МБ).

Например, возможно, /echo/subfolder1 и /echo/subfolder2 равны 300M каждый.

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

796M ./echo Эта строка есть и в списке «пропустить», и в списке «интересно»...
John Gordon 06.07.2024 22:23

Более целесообразно искать 1% файлов с наибольшим размером в крупнейших каталогах, и для этого существуют инструменты. Видеофайлы высокого разрешения занимают много места. Дисковое пространство теперь стоит дешево, поэтому, если оно действительно не заканчивается, о нем больше не стоит беспокоиться. Время от времени удалять несколько ненужных огромных файлов вполне достаточно.

Martin Brown 06.07.2024 22:35

@JohnGordon Исправлено, спасибо.

Ryan 07.07.2024 01:10

@MartinBrown Лично я не предпочитаю тратить деньги на хранение файлов, которые мне не нужны. Это законный технический вопрос, который мне интересен, и я бы хотел, чтобы люди не голосовали за него. Я уже рассматривал инструменты анализа хранилища, такие как ncdu, они классные, но недостаточно удобные.

Ryan 07.07.2024 01:13

Когда я сравниваю список того, что вам не нравится, и список того, что вам нравится, я не вижу никакой разницы (очевидно, она может быть и для вас, но я ее не вижу). Пока вы не способны провести четкое различие между вещами, которые вам нравится видеть, и остальными, как вы объясните это своему компьютеру? :-)

Dominique 08.07.2024 09:00

@Dominique Две строки, в которых я пытался описать это различие, были: because those were a waste of my attention since the output above had also included subfolders of those folders that were above the threshold that I care about и in reality, maybe any of those folders (in my most recent example) aren't even as nested / deep as they could be (the lowest level subfolders that also satisfy the threshold of 200 MB). Я мог бы попытаться написать это еще яснее, но я старался быть кратким, поскольку сообщество StackOverflow, к сожалению, предпочитает краткость даже в ущерб ясности.

Ryan 09.07.2024 00:35
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
6
130
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Иерархия каталогов — это дерево. Его узлами являются каталоги и файлы. Для файлов значением узла является его размер. Для каталогов значение узла представляет собой сумму размеров всех его дочерних элементов. Я считаю, что данная проблема состоит в том, чтобы выбрать узлы со значением, превышающим некоторый порог, все дочерние элементы которых меньше этого порога.

Как выбрать 15 крупнейших из них, уже известно.


Удобно, что du -a автоматически обеспечивает поступорядочение поиска в глубину дерева.

Итак, решение проблемы — пройтись по выходу du.

  • если путь был «виден», ничего не делайте
  • иначе, если размер превышает порог:
    • распечатать строку
    • отметить все пути предков как видимые

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

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

du -aBM /apps/ 2>/dev/null |
awk -F/ -v OFS=/ -v min=200 '
    $1+0 > min {
        raw = $0
        sub(/^[0-9]+M[ \t]+/,"") # strip size
        sub(//+$/,"") # strip trailing slashes

        if ($0 in seen) next

        print raw

        # mark ancestors as seen
        s = $1
        for (f=1; f<NF; s = s OFS $(++f))
            seen[s]
    }
' |
sort -rn | head -15

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

Это выглядит великолепно и кажется, что это может быть правильно! Спасибо! P.S. Было бы еще лучше отсортировать окончательный результат по убыванию размера. Наверное, я смогу придумать, как это сделать.

Ryan 09.07.2024 00:28

Вот хотя бы начало (сейчас нет времени дорабатывать его, чтобы избавиться от "./charlie" и преобразовать размеры файлов в байты для окончательного сравнения):

$ cat tst.sh
#!/usr/bin/env bash

sort -k2 "${@:--}" |
awk '
    {
        dir = $0
        sub(/^[^[:space:]]+[[:space:]]+/,"",dir)
    }
    index(dir,prev"/") == 1 {
        delete dirs[prev]
    }
    {
        dirs[dir] = $0
        prev = dir
    }
    END {
        for ( dir in dirs ) {
            print dirs[dir]
        }
    }
' |
sort -rn

$ cat file | ./tst.sh
1350M   ./alpha/releases
1144M   ./bravo/releases
1137M   ./charlie
1117M   ./delta/releases
871M    ./charlie/releases
794M    ./echo/releases
791M    ./alpha/releases/202210091311/node_modules
684M    ./scoreboard/node_modules

Замените cat file командой du из вопроса.

Первая строка вашего вывода — это alpha/releases, которую ОП указал как нежелательную. Это связано с тем, что он содержит 1350 МБ, а один из его подкаталогов содержит 791 МБ, поэтому максимум, который он может содержать в простых файлах, составляет (1350-791) = 559 МБ, что немного.

k314159 08.07.2024 09:52

@ k314159 k314159, как я уже упоминал в своем ответе, «вот начало...». Здесь показан типичный подход к решению подобных проблем: сначала сортировка по пути, отбрасывание родительских каталогов, а затем сортировка по размеру.

Ed Morton 08.07.2024 18:54

Похоже, опция du -S — это именно то, что вы ищете:

$ du --help
...
  -S, --separate-dirs   for directories do not include size of subdirectories
...

$ du -SBM | sort -nr | head -n 15

Приведенная выше команда должна предоставить вам список из 15 крупнейших каталогов, не считая подкаталогов. Регулируйте число head -n, пока не достигнете желаемого порога.

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

Интересный альтернативный подход. Он не будет объединять небольшие ветки и показывать их, когда общее количество превышает пороговое значение, но это может не быть проблемой.

jhnc 08.07.2024 10:58

Это выглядит интересно. Действительно простая команда. Хотя я не понимаю эту строку из справочной документации. Я только что протестировал его и не думаю, что он полностью достигает того, о чем я просил, но его легче запомнить, и он полезен в крайнем случае, потому что он помогает мне находить большие папки. Спасибо.

Ryan 09.07.2024 00:31

@Райан, что означает эта строка из справочной документации: например, если каталог содержит файлы общим размером 100 МБ, а также содержит подкаталог, который, в свою очередь, содержит 50 МБ файлов, то опция -S покажет размер каталога как 100 МБ, потому что он исключает подкаталог. Без опции -S будет отображаться 150 МБ, поскольку по умолчанию он включает подкаталоги.

k314159 09.07.2024 10:24

О, теперь я понимаю. Спасибо!!

Ryan 09.07.2024 19:32

Другие вопросы по теме