Рекурсивно удалять файлы с idx> 10000

Проблема

В текущем рабочем каталоге у меня несколько (очень много) папок, и у некоторых из них есть много (например, 100 000+) файлов внутри.

Моя цель – получить только папку с 10 000 + файлами и удалить folderName10001.ext и выше (где folderName – это фактическое имя содержащейся папки, а extлюбое расширение).

Подход

Я пытаюсь напечатать nameFolder numberOfFiles с bash .

 find . -maxdepth 1 -type d -name 'acer' -exec sh -c "echo {}; ls {} | wc -l" \; 

Это работает просто отлично (для образца папки acer ), но выход

 ./acer 6058 

Я хотел бы иметь 1-строчный вывод для каждой папки

 find . -maxdepth 1 -type d -name 'acer' -exec sh -c "echo {} `ls {} | wc -l`" \; 

говорит ls: cannot access {}: No such file or directory .


Вопросов

  1. Как я могу отобразить в одной строке nameFolder numberOfFiles ?
  2. Есть ли более простой способ удалить каждую папку folderName/folderName#.ext , с # > 10000 ?

вопрос 2

Некоторые подробности могут помочь понять, что происходит.

У меня есть папка со следующим деревом

 . ├── a │  ├── a1.ext │  ├── a2.ext │  ├── a3.ext │  └── a4.ext ├── b │  ├── b1.ext │  ├── b2.ext │  ├── b3.ext │  └── b4.ext └── c ├── c1.ext ├── c2.ext ├── c3.ext └── c4.ext 

Я хотел бы удалить каждый файл с номером больше 2 . (В моем конкретном случае порог установлен в 10000 )


Ответ 1

Это все о том, кто интерпретирует то, что (спасибо @Bratchley за советы в комментариях).

Поскольку я печатаю в bash , bash сначала интерпретирует то, что я набираю. Если я хочу, чтобы bash послал, чтобы find bash backtick , тогда мне нужно его избежать .

 find . -maxdepth 1 -type d -name 'acer' -exec sh -c "echo {} \`ls {} | wc -l;\`" \; 

который дает мне

 ./acer 6058 

@Barmar указывает, что одиночные и двойные кавычки ведут себя по-разному , и поэтому

 find . -maxdepth 1 -type d -name 'acer' -exec sh -c 'echo {} `ls {} | wc -l`' \; 

будет отлично работать (примечание " заменено на ' ).

Ответ 2

Это было сделано Уолтером А , и это принятый ответ на этот вопрос.

Больше ошибок (приведено несколько примеров) …

 black: 390120 ./clean.sh: line 6: /bin/ls: Argument list too long rm: missing operand Try 'rm --help' for more information. leather: 118240 ./clean.sh: line 6: /bin/ls: Argument list too long rm: missing operand Try 'rm --help' for more information. 

Хорошо, я исправил его с помощью

 ls -d */ | cut -d/ -f1 | while read dir; do COUNT=$(ls $dir | wc -l); if [ ${COUNT} -gt 10000 ]; then echo "$dir: ${COUNT}" ; for i in `seq 10001 ${COUNT}`; do rm ${dir}/${dir}${i}.* done fi done 

  • Замена шаблона после n-го совпадения найдена в каждой строке?
  • Как скопировать последний файл из одного каталога в другой?
  • Как избежать ряда подстановочных знаков в сценарии оболочки unix?
  • Сценарий Bash для вставки информации после каждой строки блока данных
  • Скопируйте файлы из каталога, если имя присутствует в текстовом файле
  • Как сравнить версию программы в сценарии оболочки?
  • Как перебирать переменную, пропуская одно из значений?
  • Как сортировать коллекцию строк из разных файлов?
  • 2 Solutions collect form web for “Рекурсивно удалять файлы с idx> 10000”

    Вы могли бы написать

     ls -d */ | while read dir; do echo "$dir: $(ls $dir | wc -l)" done 

    Когда имена файлов нумеруются без начальных нулей, вы можете попробовать

     ls -d */ | cut -d/ -f1 | while read dir; do COUNT=$(ls $dir | wc -l); echo "$dir: ${COUNT}" ; if [ ${COUNT} -gt 10000 ]; then ls ${dir}/${dir}?????*.ext | grep -v ${dir}/${dir}10000.ext | xargs rm fi done 

    Другой подход был бы возможен, если у вас есть ведущие нули в именах файлов:

     ls -d */ | cut -d/ -f1 | while read dir; do ls ${dir}/${dir}*.ext | tail -n +10001 | xargs rm done 

    Изменить: Включено dir + имя файла в командах ls, и я добавил cut -d/ -f1 | отрезать конечную /.

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

     find . -maxdepth 1 -type d -name 'acer' -exec sh -c 'echo {} $(ls {} | wc -l)' \; 

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

     find . -maxdepth 1 -type d -name 'acer' -exec ./scriptname {} \; 

    Таким образом вам не нужно иметь дело со всеми вопросами, связанными с использованием -exec sh -c .

    Linux и Unix - лучшая ОС в мире.