Оболочка расширяет *
, только если не заключены в кавычки, любое цитирование останавливает расширение оболочкой.
Кроме того, расширение скобок не должно быть заключено в кавычки, чтобы оболочка расширяла его.
Эта работа (позволяет использовать 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-extension).
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"
Скоба -> Переменная -> Glob || -> Скоба -> Переменная -> 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 «Расширенные шаблоны» :
#!/bin/bash
shopt -s extglob
list='@(ext1|ext2)'
ls -- *.$list
Примечание: имейте в виду, что оба решения (eval и шаблоны) (как написано) безопасны для имен файлов с пробелами. или новые строки. Но не получится для $ list
с пробелами, потому что $ list
не заключен в кавычки или eval удаляет кавычки.