Оболочка Bash: список всех файлов типа .png или .PNG?

14

В скрипте bash, как я могу сказать «для всех файлов типа .png или .PNG»?

Я стараюсь :

for i in (`ls *.PNG` && `ls *.png`)

но получаю синтаксическую ошибку.

Саймон
источник

Ответы:

18

Если вы хотите все возможные комбинации, используйте:

for i in *.[Pp][Nn][Gg]; do

или

shopt -s nocaseglob
for i in *.png; do

хотя это сделает все глобусы оболочки вашего скрипта (т.е. совпадения с подстановочными файлами) нечувствительными к регистру, пока вы не запустите shopt -u nocaseglob.

Если вы действительно хотите просто .PNG и .png (а не, например, .PnG или .pnG), используйте либо

shopt -s nullglob
for i in *.png *.PNG; do

или

for i in *.png *.PNG; do
    [[ -e "$i" ]] || continue

... причина проверки nullglob или существования заключается в том, что если у вас есть только расширения в нижнем или только верхнем регистре, он включит несогласованный шаблон в список файлов, что приведет к ошибке в теле цикла. Как и в случае с nocaseglob, вы, возможно, захотите позже отключить опцию оболочки nullglob (хотя, по моему опыту, включение nullglob часто хорошо, особенно в сценарии). На самом деле, я скорее считаю хорошей идеей использовать либо nocaseglob, либо проверку существования для всех совпадений файлов, как это, на случай, если совпадений нет.

Гордон Дэвиссон
источник
5
for i in *.{png,PNG}
Гленн Джекман
@glenn: Это тоже сработало бы (эквивалентно `* .png * .PNG), хотя вам все еще нужен nullglob или проверка существования.
Гордон Дэвиссон
5

Вы также можете попробовать некоторые однострочные, такие как

находить . -имя "* .png" -exec ....

или

находить . -имя "* .png" | xargs ....

Редактировать
Смотрите также комментарий @ Yab ниже о рекурсии.

Ален Паннетье
источник
1
Однако по умолчанию поиск является рекурсивным, поэтому, чтобы получить тот же результат, который задает вопрос, вам придется это сделать find -maxdepth 1 -iname "*.png"
Яб
@ Яб, ты совершенно прав. Я упустил из виду этот аспект.
Ален Паннетье
1

ls здесь почти бесполезен, но для записи вот синтаксис, более близкий к вашей попытке:

for i in $(ls *.PNG ; ls *.png)

Примечания:

  • Я предполагаю, что вы хотите и заглавные и строчные картинки. Разделитель && будет означать обработку файлов PNG, только если существуют файлы PNG, что, вероятно, не имеет особого смысла.
  • у вас будут отображаться сообщения об ошибках, если ни один из файлов не найден.
jlliagre
источник