найти xargs rm с шаблоном имени файла в переменной

найти xargs rm с шаблоном имени файла в переменной

Команда типа этой:

find /directory -type f -name "*.txt" -print | xargs rm

удалить все .txtфайлы в каталоге и подкаталогах, и это нормально. Но, если мы создадим переменную или массив для расширения файла, а затем поместим find, например,

TXT=(*.txt)
for ii in ${TXT[@]}; do
  find /directory -type f -name $TXT -print | xargs rm
done

эти команды не удаляют .txtфайлы в подкаталогах. Почему? Как изменить этот второй код, чтобы удалять файлы в подкаталогах?

PS: Я использовал массив, так как у меня несколько расширений файлов.

решение1

Ваше назначение массива,

TXT=(*.txt)

расширит *.txtшаблон до списка имен файлов в текущем каталоге, которые соответствуют этому шаблону. Оболочка сделает это во время назначения. Это не то, что вам нужно. Вы хотите задать findлитеральную строку *.txt, например:

pattern='*.txt'
find /directory -type f -name "$pattern" -exec rm {} +

Здесь я также избавился от xargs rmи вместо этого выполняю rmнапрямую из find. Большинство текущих реализаций findмогли бы использовать нестандартный -deleteвместо -exec rm {} +:

pattern='*.txt'
find /directory -type f -name "$pattern" -delete

Обратите внимание, что здесь нет необходимости в цикле, поскольку мы имеем дело только с одним шаблоном. Также обратите внимание, что кавычки "$pattern"в вызове findважны, иначе шаблон будет заменен всеми соответствующими именами файлов в текущем каталоге перед findзапуском.

Для нескольких шаблонов можно сделать такой цикл:

patterns=( '*.txt' '*.tmp' )
for pattern in "${patterns[@]}"; do
    find /directory -type f -name "$pattern" -delete
done

Кавычки в назначении массива необходимы, поскольку они не позволяют оболочке использовать шаблоны в качестве шаблонов подстановки имен файлов. Кавычки "${patterns[@]}"и "$pattern"также важны по той же причине.

Другой подход — сделать только один вызов find, даже если у вас есть несколько шаблонов. Это немного ускорит работу, если /directoryэто большая иерархия каталогов. Следующий код делает это, создавая массив -nameтестов для findиспользования:

patterns=( '*.txt' '*.tmp' )

name_tests=( )
for pattern in "${patterns[@]}"; do
    name_tests+=( -o -name "$pattern" )
done

# "${name_tests[@]:1}" removes the initial "-o", which shouldn't be there.
name_tests=( '(' "${name_tests[@]:1}" ')' )

find /directory -type f "${name_tests[@]}" -delete

В приведенном выше скрипте фактическая команда, выполняемая в конце, будет следующей:

find /directory -type f '(' -name '*.txt' -o -name '*.tmp' ')' -delete

... который удалит все обычные файлы, имеющие суффиксы в именах файлов.txt или .tmpв любом месте каталога или ниже /directory.

Связанный контент