Я пытаюсь запустить цикл for, но пытаюсь исключить файлы с определенным шаблоном в имени файла. Это команда, которую я использую:
for file in /home/ubuntu/discovery/download/*![.en].mp4; do
Я хотел бы, чтобы это имя файла было включено:
Blub - S03E10 - Nervous Breakdown.mp4
но это имя файла исключить
Blub - S03E10 - Nervous Breakdown.en.mp4
Не могу заставить его работать. Что я делаю не так?
заранее спасибо
@markp-fuso Синтаксис questioni близок к правильному! Смотрите мой ответ!
Что я делаю не так?
В стандартной подстановке нет операторов группировки или группового отрицания (хотя в расширенной версии они есть). В вашем конкретном контексте я бы просто отфильтровал ненужные файлы внутри цикла:
for file in /home/ubuntu/discovery/download/*.mp4; do
case $file in
*.en.mp4) continue;;
esac
# ...
done
И это должно работать в любой оболочке семейства Bourne, а не только в Bash.
extglob
:!(pattern-list) Matches anything except one of the given patterns
Попробуй это:
for file in /home/ubuntu/discovery/download/!(*.en).mp4; do
...
Если нет файлов, соответствующих шаблону глобуса, file
будет установлен на шаблон глобуса. Либо убедитесь, что путь в file
существует, либо включите nullglob
с помощью shopt -s nullglob
.
Правильно., но это то же самое поведение, что и /path/*
! Вы можете проверить, используя [ -$àfile ]
...
Один вопрос: почему !(*.en).mp4
работает, а *!(.en).mp4
нет?
@Филипп, потому что узор должен начинаться с !
. Ака !(...)
правильно, *!( ...)
— неизвестная модель. См. Удаление всех файлов, кроме некоторых, из каталога
Другой подход заключается в переборе всех файлов, пропуская те, которые имеют нежелательные шаблоны имен. Просто не забудьте также обработать случай, когда файлы не найдены, потому что в этом случае file
устанавливается равным шаблону глобуса. Часто вы можете справиться с этой ситуацией, убедившись, что путь в file
действительно существует (-e "${file}"
).
for file in /home/ubuntu/discovery/download/*.mp4; do
[[ -e "${file}" && "${file}" != *.en.mp4 ]] || continue
echo ${file}
done
Другой альтернативой может быть:
shopt -s nullglob
for file in /home/ubuntu/discovery/download/*{[^n],[^e]n,[^.]en}.mp4
do
# ...
done
Я бы посоветовал вам использовать
find
для создания списка нужных файлов (без исключений), а затем передать этот список в циклwhile/read
, например,while read -r fname; do do_some_stuff_with_fname; done < <(find /home/unbuntu/discovery/download ... exclude_some_file_types ...)