Найдите папки размером меньше x и удалите их

Я хочу найти все папки (внутри папки) размером менее 100 МБ и удалить их. Я на самом деле не хочу использовать скрипт bash. Но, вероятно, есть некоторая изящная возможность в одну строку сделать это. Но, к сожалению, мои знания оболочки не так уж хороши

Что я пробовал

 du -sh * | grep -E "^[0-9]{1,2}M" | xargs -0 rm

Это не будет работать, так как вывод du -sh * | grep _E ".." кажется одной строкой.

Что я тоже пробовал

find . -maxdepth 1 -type d -size 100M [-delete]

Но я думаю, -size флаг не то, что я ищу

2 ответа

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

find . -maxdepth 1 -type d | 
  while read dir; do [ $(du -s "$dir") -le 102400 ] && rm -f "$dir"; done

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

find . -maxdepth 1 -type d -print0 | while IFS= read -r -d '' dir; do
    [ $(du -s "$dir") -le 102400 ] && rm -f "$dir"
done

Так как это будет обрабатывать подкаталоги раньше своих родителей, к тому времени dir1 обрабатывается, dir2 а также dir3 будет уже удален, поэтому его размер будет ниже порогового значения, и он тоже будет удален. Хотите ли вы этого на самом деле, будет зависеть от того, что именно вы пытаетесь сделать.


Это, однако, упрощенный подход. Рассмотрим следующий сценарий:

$ tree -h
.
`-- [4.0K]  dir1
    |-- [4.0K]  dir2
    |   `-- [ 80M]  file1
    `-- [4.0K]  dir3
        `-- [ 80M]  file2

3 directories, 2 files

Здесь у нас есть 2 подкаталога под dir1каждый из которых содержит файл 80M. Команда выше сначала найдет dir1 чей размер>100M, поэтому он не будет удален. Затем он найдет dir1/dir2 а также dir1/dir3 и удалите их обоих, так как они <100M. Конечный результат будет пустым dir1 чей размер, конечно, будет <100M, так как он пуст.

Таким образом, это решение будет хорошо работать, если у вас есть только один уровень подкаталогов. Если у вас более сложные файловые структуры, вам нужно подумать о том, как вы хотите с этим справиться. Одним из подходов будет использование -depth который гарантирует, что подкаталоги будут показаны первыми:

find . -depth -maxdepth 1  -type d -print0 | while IFS= read -r -d '' dir; do
    [ $(du -s "$dir") -le 102400 ] && rm -f "$dir"
done

Сюда, dir1 будет обработан после dir2 а также dir3 поэтому он будет пустым, выйдет за пределы порога и также будет удален. Хотите вы этого или нет, будет зависеть от того, что именно вы пытаетесь сделать.

С помощью du с флагом -h проводить сравнение значений, как правило, плохая идея.

Команда, которую вы ищете:

find . -maxdepth 1 -type d | grep -v ^\\.$ | xargs -n 1 du -s | while read size name ; do if [ $size -gt 104857600 ] ; then echo rm -rf $name ; fi done

Объяснение:

  • find . -maxdepth 1 -type d находит все подкаталоги текущего каталога
  • grep -v ^\\.$ исключает текущий каталог (.)
  • xargs -n 1 передает их одну за другой следующей команде
  • du -s обеспечивает суммарное (т. е. общее) пространство файлов в этом каталоге
  • while read size name... done выполняет цикл над своим вводом, считывая размер и имя каждого каталога
  • остальное более или менее понятно.

Как только вы довольны командой, удалите echo до rm -rf

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