#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/...
, если вы хотите сбрить несколько байтов 🙂