Оболочка расширяется *
только тогда , когда расширение не-цитируемым, любая ссылка останавливается оболочкой.
Кроме того, расширение скобки должно быть без кавычек, чтобы быть расширенным оболочкой.
Эта работа (давайте посмотрим на echo, что делает оболочка):
$ echo *.{ext1,ext2}
a.ext1 b.ext1 a.ext2 b.ext2
Даже если есть файлы с некоторыми другими именами:
$ touch {a,b}.{ext1,ext2} {c,d}.{ext3,ext4} none
ls
a.ext1 a.ext2 b.ext1 b.ext2 c.ext3 c.ext4 d.ext3 d.ext4 none
$ echo *.{ext1,ext2}
a.ext1 b.ext1 a.ext2 b.ext2
Почему это работает?
Важно, чтобы мы понимали, почему это работает. Это из-за порядка расширения. Сначала «Расширение скобок», а затем (последнее) «Расширение пути» (он же glob-расширение).
Brace --> Parameter (variable) --> Pathname
Мы можем отключить «Расширение пути» на мгновение:
$ set -f
$ echo *.{ext1,ext2}
*.ext1 *.ext2
«Расширение пути» получает два аргумента: *.ext1
и *.ext2
.
$ set +f
$ echo *.{ext1,ext2}
a.ext1 b.ext1 a.ext2 b.ext2
Проблема в том, что мы не можем использовать переменную для расширения скобки.
Это было объяснено много раз прежде для использования переменной внутри «расширения скобки»
Чтобы развернуть «Расширение скобок», являющееся результатом «Расширения переменных», необходимо повторно передать командную строку в оболочку с помощью eval
.
$ list={ext1,ext2}
$ eval echo '*.'"$list"
Brace -> Variable -> Glob || -> Brace -> Variable -> Glob
........ цитируется здесь -> ^^^^^^ || eval ^^^^^^^^^^^^^^^^^^^^^^^^^
Значения имен файлов не вызывают проблем с выполнением для eval:
$ touch 'a;date;.ext1'
eval echo '*.'"$list"
a;date;.ext1 a.ext1 b.ext1 a.ext2 b.ext2
Но ценность $list
может быть небезопасной. Однако значение $list
устанавливается автором сценария. Автор сценария контролирует eval
: Просто не используйте внешние значения для $list
. Попробуй это:
#!/bin/bash
touch {a,b,c}.ext{1,2}
list=ext{1,2}
eval ls -l -- '*.'"$list"
Лучшая альтернатива.
Альтернативой (без eval) является использование Bash «Extended Patterns» :
#!/bin/bash
shopt -s extglob
list='@(ext1|ext2)'
ls -- *.$list
Примечание. Обратите внимание, что оба решения (eval и pattern) (как написано) безопасны для имен файлов с пробелами или новыми строками. Но потерпит неудачу для $list
с пробелами, потому $list
что без кавычек или Eval удаляет кавычки.
eval ls $secondList
отлично работает здесь ... что вы пытаетесь достичь?