Рекурсивний глобус?


80

Я хотів би написати щось подібне:

$ ls **.py

щоб отримати всі .py імена файлів, рекурсивно переходячи до ієрархії каталогів.

Навіть якщо є .py файли для пошуку, оболонка (bash) дає такий вихід:

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

Будь-який спосіб робити те, що я хочу?

EDIT: Я хотів би зазначити, що мене не цікавить конкретний випадок ls, але питання стосується глобального синтаксису.

Відповіді:


98

Для того, щоб робити рекурсивні глобуси в bash, вам потрібна globstarфункція від bash версії 4 або вище.

З баш-сторінки:

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
glenn jackman

6
@glennjackman Але перед тим, як включити nullglob, я б настійно радив прочитати наступні попередження .
Серж Стротобандт

2
^ Попередження перенесли сюди .
usandfriends

1
З басом 3.2, wc -l {**,.}/*.pyпрацює чудово
Рафаель,

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

10
find . -name '*.py'

** не робить нічого більше, ніж один *, обидва працюють у поточному каталозі


Цікаво. Хоча я більше зосереджений на синтаксисі глобула сам по собі, тому що мені доводиться використовувати його у файлі конфігурації (включати директиву). Мені не потрібен список файлів.
Паоло

2
@Doug O'Neal, це вже не так. bash тепер скопіював цю функцію zsh (хоча вона прийняла синтаксис, ближчий до ksh93 і як ksh, але не підтримує класифікатори zsh, але обмежує його корисність)
Stéphane Chazelas

Є багато речей, які ви можете зробити, findякщо у вас немає yourcommand `find . -name '*.py'`грифу. find . -name '*.py' -exec yourcommand {} \;.
Марс

5

Оскільки Bash 4 (також включаючи zsh) додано новий варіант глобалізації ( globstar), який трактує шаблон по- **різному, коли він встановлений.

Це узгодження шаблону підстановки та повернення імен файлів та каталогів, які відповідають тому, замінивши шаблон шаблону в команді на відповідні елементи.

Зазвичай, коли ви користуєтеся **, він працює аналогічно *, але він рекурсує всі каталоги рекурсивно (як цикл).

Щоб побачити, чи ввімкнено це, перевірте це за допомогою shopt globstar(сценаріїв, використання shopt -q globstar).

Приклад **.pyможе працювати лише для поточного каталогу, оскільки він не повертає список каталогів, який може бути повторним, тому для цього вам потрібно використовувати декілька підстановок на рівні каталогів **/*.py, щоб він заглиблювався.

Будь ласка, знайдіть на ТАКІ кілька тестів на синтаксис, які я зробив для пошуку рекурсивних файлів.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.