Рекурсивный шар?


80

Я хотел бы написать что-то вроде этого:

$ ls **.py

чтобы получить все .py имена файлов, рекурсивно обходить иерархию каталогов.

Даже если есть файлы .py, которые нужно найти, оболочка (bash) выдает следующее:

ls: cannot access **.py: No such file or directory

Любой способ сделать то, что я хочу?

РЕДАКТИРОВАТЬ: Я хотел бы указать, что я не заинтересован в конкретном случае ls, но вопрос о синтаксисе glob.

Ответы:


98

Для создания рекурсивных шаров в bash вам нужна globstarфункция из bash версии 4 или выше.

Из справочной страницы bash:

globstar
    If set, the pattern ** used in a pathname expansion context will
    match all files and zero or more directories and subdirectories.
    If the pattern is followed by a /, only directories and
    subdirectories match.

Для вашего примера шаблона:

shopt -s globstar
ls **/*.py

2
Я бы порекомендовал также включитьnullglob
Гленн Джекман

6
@glennjackman Но перед включением nullglobя настоятельно рекомендую прочитать следующие предупреждения .
Серж Строобандт

2
^ Предупреждения перенесены сюда .
usandfriends

1
С bash 3.2 wc -l {**,.}/*.pyработает просто отлично
Рафаэль

@Raphael Я дважды проверил примечания к выпуску, и он определенно говорит, что он был представлен в 4.0. Возможно, в вашем дистрибутиве есть патч для него? IIRC RHEL 5 поддерживал некоторые функции. Также следует отметить, что прошло 9 лет с момента выхода bash 4 ...
Иордания,

10
find . -name '*.py'

** не делает ничего, кроме одного *, оба работают в текущем каталоге


Интересно. Тем не менее, я больше сосредоточен на синтаксисе glob сам по себе, потому что я должен использовать его в файле конфигурации (директива include). Мне не нужен список файлов.
Паоло

2
@ Дуг О'Нил, это больше не правда. bash теперь скопировал эту функцию zsh (хотя он принял синтаксис, близкий к синтаксису ksh93 и, подобно ksh, пока не поддерживает глобальные классификаторы zsh, что ограничивает его полезность)
Стефан Шазелас

Есть много вещей, с которыми вы можете делать, findесли у вас нет bash 4. Примеры: yourcommand `find . -name '*.py'`(обратите внимание на обратные ссылки); find . -name '*.py' -exec yourcommand {} \;,
Марс

5

Начиная с Bash 4 (также включая zsh) была добавлена ​​новая опция globbing ( globstar), которая обрабатывает шаблон по- **разному, когда он установлен.

Он сопоставляется с шаблоном подстановки и возвращает имена файлов и каталогов, которые затем соответствуют, заменяя шаблон подстановки в команде соответствующими элементами.

Обычно при использовании **он работает аналогично *, но рекурсивно рекурсивно обращается ко всем каталогам (например, цикл).

Чтобы увидеть, включен ли он, проверьте его с помощью shopt globstar(в сценариях используйте shopt -q globstar).

Этот пример **.pyбудет работать только для текущего каталога, так как он не возвращает список каталогов, которые могут быть рекурсивными, поэтому вам нужно использовать несколько подстановочных знаков уровня каталога **/*.py, чтобы он мог идти глубже.

Пожалуйста, найдите на SO несколько синтаксических тестов, которые я сделал для рекурсивного поиска всех файлов.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.