] вместо этого используйте []zsh[
]:[
setopt extendedglob
for f ($arg/**/*.(#i)(txt|h|py)(N.)) {
...
}
]
[]**/[
]: любой уровень подкаталогов[](#i)[
] должен включать нечувствительное к регистру совпадение для остальной части глобуса (как []~(i)[
] в []ksh93[
]). [](N.)[
] является классификатором глобуса. []N[
] должен не возвращать ошибку, если нет соответствующего файла и [].[
] должен выбирать только обычные файлы (эквивалент [] найти [
] -тип f[]-тип f[
]))). Вы можете добавить туда []D[
], чтобы также сопоставить точечные (скрытые) файлы и спуститься в скрытые папки (как []find[
] по умолчанию).[ В bash
можно установить nocaseglob
:
shopt -s nocaseglob
for file in "$arg"/**/*.{txt,h,py}
do
....
done
shopt -u nocaseglob
noclaseglob
можно использовать в любом bash
, начиная с 2. 01, однако **
требует bash
4.0 или более поздней версии (и это следует за сим-связью до bash
4.3, где она была зафиксирована). Обратите внимание на исправление цитаты $arg
, так как будут проблемы, если она содержит пробелы или глобусные символы.
Не используя **
вы можете сделать что-то вроде:
find "$arg" \( -iname '*.txt' -o -iname '*.h' -o -iname '*.py' \) -exec bash -c '
for file; do
...
done' bash {} +
Это найдет все файлы, которые вы ищете, и передаст их как отдельные аргументы новому экземпляру bash, который затем процитирует их. Если ваша операция для каждого файла - это одна команда, вы, вероятно, можете пропустить новый bash-объект и использовать эту команду напрямую.
В соответствии с комментариями Стефана, приведенными ниже, совместимое с POSIX решение:
find "$arg" \( -name '*.[tT][xX][tT]' -o -name '*.[hH]' -o -name '*.[pP][yY]' \) \
-exec sh -c '
for file do
...
done' sh {} +
Как насчет простого:
for file in "$(ls -1 | grep -iE '\.txt|\.py|\.h')";
do
....
done
Другой простой вариант:
find . -maxdepth 1 -iname '*.txt'; find . -maxdepth 1 -iname '*.py'; find . -maxdepth 1 -iname '*.h';
Вы можете оберните find в круглые скобки $() в bash, чтобы получить список.