Как удалить папки, которые имеют n или меньше файлов в них?

Я должен сделать некоторую очистку папки, и я хотел бы удалить каталоги, которые имеют 10 или меньше файлов в них. Я пытался смотреть на GNU find, но не было ничего связанного с количеством файлов в каталоге. Какие команды я должен использовать для выполнения этого?

7
задан 21 July 2016 в 12:45

2 ответа

Я не полностью протестировал это, но это должно работать. Можно также использовать find для выполнения этого.

# Loop over all files
for dir in * **/*; do
    # Make sure this is a directory
    if [ -d "${dir}" ]; then
        # Get the number of files (not including directories) in this directory
        FILE_COUNT=`ls $dir -1 | grep -v / | wc -l`
        # Check if it's less than 10
        if [ $FILE_COUNT -lt 10 ]; then
            # Delete the directory
            rm -rf "${dir}"
        fi
    fi
done
0
ответ дан 23 November 2019 в 06:51

Один путь состоял бы в том, чтобы использовать find -exec действие для выполнения пользовательского теста количества файлов.

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

files=( dir/* ); ((${#files[@]} < 10))

Соединяя все это, мы должны смочь перечислить все подкаталоги меньше чем с 10 файлами (включая подподкаталоги) использование

find . -depth -type d ! -name '.' -exec bash -c '
  shopt -s nullglob; files=( "$1"/* ); ((${#files[@]} < ${2:-10}))
  ' bash {} 10 \; -print0 | xargs -0

(можно скорректировать число 10 после bash {} для различных порогов - ${2:-10} расширение параметра делает это значением по умолчанию в 10 файлов, если никакой второй аргумент не дан). Например, данный

$ tree .
.
├── bar
│  ├── file1
│  ├── file2
│  ├── file3
│  ├── file4
│  ├── file5
│  ├── file6
│  ├── file7
│  ├── file8
│  ├── file9
│  └── other file
├── baz
│  ├── other file
│  └── subdir
└── foo
    └── somefile

4 directories, 12 files

затем

find . -depth -type d ! -name '.' -exec bash -c '
  shopt -s nullglob; files=( "$1"/* ); ((${#files[@]} < "${2:-10}"))
  ' bash {} 10 \; -print0 | xargs -0
./foo ./baz/subdir ./baz

Если это, кажется, делает правильную вещь, можно на самом деле удалить их путем добавления rm -rf но будьте очень осторожны с этим - помнят, что нет никакой 'отмены'

find . -depth -type d ! -name '.' -exec bash -c '
  shopt -s nullglob; files=( "$1"/* ); ((${#files[@]} < ${2:-10}))
' bash {} 10 \; -print0 | xargs -0 rm -rf

( xargs мог быть устранен при помощи другого -exec действие для выполнения rm более непосредственно, но формулировка выше помогает сделать вывод - печать, статистика, удалить или что бы то ни было.)

Обратите внимание, что это будет действовать рекурсивно т.е. каталог, который первоначально имеет больше, чем n файлы включая подкаталоги могут быть удалены в результате некоторых из тех подкаталогов, самих удаляемых как find создает резервную копию дерева каталогов - текущий каталог явно защищен от возможного удаления ! -name '.' тест.

Если Вам не нужен он для действия рекурсивно, можно просто циклично выполниться по каталогам и выполнить то же количество файла и протестировать логику, например, удалить все каталоги первого уровня, содержащие меньше чем 10 файлов в текущем каталоге

shopt -s nullglob
for d in */; do
  files=( "$d"/* )
  ((${#files[@]} < 10)) && echo rm -rf -- "$d"
done 
3
ответ дан 23 November 2019 в 06:51

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

Похожие вопросы: