Найдите папки размером меньше 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