Как циклически перебирать каталог для удаления файлов с определенными расширениями

Мне нужно циклически перебирать каталог и удалять все файлы с расширением .pdf и.doc, мне удается рекурсивно перебирать каталог, но не удалять файлы для фильтрации с вышеупомянутыми расширениями файлов.

Мой код до сих пор

#/bin/sh SEARCH_FOLDER="/tmp/*" for f in $SEARCH_FOLDER do if [ -d "$f" ] then for ff in $f/* do echo "Processing $ff" done else echo "Processing file $f" fi done 

Мне нужна помощь для завершения кода, так как я никуда не денусь.

find просто сделан для этого.

 find /tmp -name '*.pdf' -or -name '*.doc' | xargs rm 

В ответ на ответ мувициля вы также можете сделать это как цикл for, вместо использования xargs. Я часто нахожу xargs громоздким, особенно если мне нужно сделать что-то более сложное на каждой итерации.

 for f in $(find /tmp -name '*.pdf' -or -name '*.doc'); do rm $f; done 

Как прокомментировал ряд людей, это не удастся, если в именах файлов есть пробелы. Вы можете обойти это, временно установив IFS (внутренний разделитель полей) на символ новой строки. Это также не удается, если в именах файлов есть подстановочные знаки \[?* . Вы можете обойти это, временно отключив расширение подстановки (globbing).

 IFS=$'\n'; set -f for f in $(find /tmp -name '*.pdf' -or -name '*.doc'); do rm "$f"; done unset IFS; set +f 

Если у вас есть новые строки в ваших именах файлов, это тоже не сработает. Вам лучше с решением xargs:

 find /tmp \( -name '*.pdf' -or -name '*.doc' \) -print0 | xargs -0 rm 

( -print0 скобки необходимы здесь для -print0 к обоим or предложениям.)

GNU и * BSD find также имеют действие -delete , которое будет выглядеть так:

 find /tmp \( -name '*.pdf' -or -name '*.doc' \) -delete 

Без find :

 for f in /tmp/* tmp/**/* ; do ... done; 

/tmp/* – файлы в каталоге dir и /tmp/**/* – файлы в подпапках. Возможно, вам нужно включить опцию shopt -s globstar ( shopt -s globstar ). Поэтому для вопроса код должен выглядеть так:

 shopt -s globstar for f in /tmp/*.pdf /tmp/*.doc tmp/**/*.pdf tmp/**/*.doc ; do rm "$f" done 

Обратите внимание, что для этого требуется bash ≥4.0 (или zsh без shopt -s globstar или ksh с set -o globstar вместо shopt -s globstar ). Кроме того, в bash <4.3 это пересекает символические ссылки на каталоги, а также каталоги, что обычно нежелательно.

Если вы хотите сделать что-то рекурсивно, я предлагаю вам использовать рекурсию (да, вы можете сделать это с помощью стеков и т. Д., Но эй).

 recursiverm() { for d in *; do if [ -d "$d" ]; then (cd -- "$d" && recursiverm) fi rm -f *.pdf rm -f *.doc done } (cd /tmp; recursiverm) 

Тем не менее, find , вероятно, лучший выбор, как уже было предложено.

Вот пример использования shell ( bash ):

 #!/bin/bash # loop & print a folder recusively, print_folder_recurse() { for i in "$1"/*;do if [ -d "$i" ];then echo "dir: $i" print_folder_recurse "$i" elif [ -f "$i" ]; then echo "file: $i" fi done } # try get path from param path="" if [ -d "$1" ]; then path=$1; else path="/tmp" fi echo "base path: $path" print_folder_recurse $path 

Это не отвечает на ваш вопрос напрямую, но вы можете решить свою проблему с помощью однострочного интерфейса:

 find /tmp \( -name "*.pdf" -o -name "*.doc" \) -type f -exec rm {} + 

В некоторых версиях find (GNU, BSD) есть действие -delete которое вы можете использовать вместо вызова rm :

 find /tmp \( -name "*.pdf" -o -name "*.doc" \) -type f -delete 

Этот метод хорошо обрабатывает пространства.

 files="$(find -L "$dir" -type f)" echo "Count: $(echo -n "$files" | wc -l)" echo "$files" | while read file; do echo "$file" done 

Редактировать, исправлять по очереди

 function count() { files="$(find -L "$1" -type f)"; if [[ "$files" == "" ]]; then echo "No files"; return 0; fi file_count=$(echo "$files" | wc -l) echo "Count: $file_count" echo "$files" | while read file; do echo "$file" done } 

Следующая функция рекурсивно перебирает все каталоги в каталоге \home\ubuntu (целая структура каталогов под ubuntu) и применяет необходимые проверки в блоке else .

 function check { for file in $1/* do if [ -d "$file" ] then check $file else ##check for the file if [ $(head -c 4 "$file") = "%PDF" ]; then rm -r $file fi fi done } domain=/home/ubuntu check $domain 

Для bash (начиная с версии 4.0):

 shopt -s globstar nullglob dotglob echo **/*".ext" 

Это все.
Конечное расширение «.ext» позволяет выбирать файлы (или dirs) с этим расширением.

Опция globstar активирует ** (поиск повторяется).
Параметр nullglob удаляет *, когда он не соответствует файлу / директории.
Опция dotglob включает файлы, начинающиеся с точки (скрытые файлы).

Помните, что до bash 4.3, **/ также пересекает символические ссылки на каталоги, которые нежелательны.

Просто делать

 find . -name '*.pdf'|xargs rm 

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

for d in /home/ubuntu/*; do echo "listing contents of dir: $d"; ls -l $d/; done

  • Почему мой счетчик Bash сбрасывается после цикла while
  • Как использовать значение переменной как имя другой переменной в bash
  • Как передать символ asterisk '*' в bash в качестве аргументов моей программе на C?
  • Получить путь к файловому каталогу из пути к файлу
  • Как скрипт bash выполняет эквивалент Ctrl-C для фоновой задачи?
  • Объяснение оператора двоеточия в:: $ {foo = value}
  • Как показать и обновить эхо на одной строке
  • Bash расширяет переменную переменной
  • отменить порядок символов в строке
  • Backticks против брекетов в Bash
  • Возможно ли, чтобы команды bash продолжались до результата предыдущей команды?
  • Interesting Posts

    Использование regex lookbehinds в C ++ 11

    Являются ли словари упорядоченными в Python 3.6+?

    Oracle.ManagedDataAccess.EntityFramework – ORA-01918: пользователя ‘dbo’ не существует

    Автоматически запускать программу, когда Mac просыпается

    Где я могу найти версию streamа данных TPL для 4.0?

    Отправить форму при нажатии Enter с помощью AngularJS

    Как узнать, что мой WebView загружен на 100%?

    Windows 10 указывает отсутствие сетевого кабеля после обновления или юбилейного обновления

    Не удается закрыть Excel.exe после процесса Interop

    Как связать команду в WPF с обработчиком события двойного щелчка элемента управления?

    Как создать общеansible / частный профиль пользователя с правилами безопасности Firebase?

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

    Ограничение доступа к дискам томов даже для окон учетной записи администратора

    Как вы проверяете веб-инспектора в хроме?

    Android: HTTP-связь должна использовать «Accept-Encoding: gzip»

    Давайте будем гением компьютера.