Скрипт Bash удаляет все файлы, кроме нескольких файлов

#bash

Вопрос:

У меня есть свой сценарий bash

 #!/bin/bash
set -euxo pipefail
I_PATH=$(pwd)

shopt -s extglob 

for BASE in Adenina Citocina Guanina Timina
do
    cd ${BASE}
    rm !(*.psf|*.fdf|siesta|*.log)
    cd ${I_PATH}
done
 

Я хочу, чтобы он удалил все файлы, кроме исключенных файлов. Проблема в том, что bash выполняет команду следующим образом

 rm '!(*.psf|*.fdf|siesta|*.log)'
 

Затем сценарий завершается ошибкой с

 rm: cannot remove '!(*.psf|*.fdf|siesta|*.log)': No such file or directory
 

Как я могу предотвратить, чтобы скрипт добавлял » в команду?

Комментарии:

1. Они ' добавляются только в сообщение. Если вы не включили их в команду, они не будут добавлены перед выполнением.

Ответ №1:

используйте команду найти

 for BASE in Adenina Citocina Guanina Timina
do
  find ${BASE} -type f ! -name "*.psf" ! -name "*.fdf" ! -name "siesta" ! -name"*.log" -delete
done
 

Комментарии:

1. С find Adenina Citocina ... -type ... вами не нужна петля. В зависимости от требований OP вы можете захотеть добавить -maxdepth 1 .

2. Почему? имя каталога может быть «сиеста» или «mydir.log/».

3. Если одно из исключенных имен является каталогом, (часть) его содержимого может быть удалено, поскольку -delete подразумевает -depth . Вот почему я предложил -maxdepth . Но поскольку OP принял этот ответ, похоже, что все исключенные имена были файлами.

Ответ №2:

Похоже, что для вашего глобуса нет совпадений, в результате чего глобус будет рассматриваться как литеральная строка. Включите nullglob для расширения до нуля в случае отсутствия совпадений

rm без каких-либо аргументов может появиться ошибка, поэтому мы также используем rm -f .

Кстати: Глобусы работают с расширением скобок. Вам не нужна петля или cd .

 shopt -s nullglob
shopt -s extglob
rm -f {Adenina,Citocina,Guanina,Timina}/!(*.psf|*.fdf|siesta|*.log)
 

Или {Aden,Citoc,Guan,Tim}ina/... , если вы хотите сбрить несколько байтов 🙂