Glo ricorsivo?


80

Vorrei scrivere qualcosa del genere:

$ ls **.py

per ottenere tutti i nomi di file .py, camminando ricorsivamente in una gerarchia di directory.

Anche se ci sono file .py da trovare, la shell (bash) fornisce questo output:

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

Qualche modo per fare quello che voglio?

EDIT: Vorrei specificare che non sono interessato al caso specifico di ls, ma la domanda riguarda la sintassi globale.

Risposte:


98

Per eseguire globi ricorsivi in ​​bash, è necessaria la globstarfunzione dalla versione 4 o successiva di bash.

Dalla manpage di 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.

Per il tuo esempio di esempio:

shopt -s globstar
ls **/*.py

2
Consiglierei anche di abilitarenullglob
glenn jackman il

6
@glennjackman Ma prima di abilitare nullglob, consiglio vivamente di leggere le seguenti avvertenze .
Serge Stroobandt,

2
^ Gli avvisi sono stati spostati qui .
usandfriends

1
Con bash 3.2, wc -l {**,.}/*.pyfunziona benissimo
Raphael,

@Raphael Ho ricontrollato le note di rilascio e dice sicuramente che è stato introdotto in 4.0. Forse la tua distribuzione ha eseguito il backport di una patch per questo? IIRC RHEL 5 aveva eseguito il backport di alcune funzionalità. Inoltre, sono passati 9 anni da quando Bash 4 è stato rilasciato ...
Giordania,

10
find . -name '*.py'

** non fa altro che un singolo *, entrambi operano nella directory corrente


Interessante. Tuttavia, sono più concentrato sulla sintassi glob da solo, perché devo usarlo in un file di configurazione (direttiva include). Non ho bisogno di un elenco di file.
Paolo,

2
@Doug O'Neal, non è più vero. bash ora ha copiato quella funzione di zsh (sebbene abbia adottato una sintassi più vicina a quella di ksh93 e come ksh, non supporta ancora le qualificazioni di globbing di zsh che ne limitano l'utilità)
Stéphane Chazelas

Ci sono molte cose che puoi fare findse non hai bash 4. Esempi: yourcommand `find . -name '*.py'`(nota i backtick); find . -name '*.py' -exec yourcommand {} \;.
Marte,

5

Da Bash 4 (incluso anche zsh) è stata aggiunta una nuova opzione globbing ( globstar) che tratta lo schema in modo **diverso quando è impostato.

Corrisponde al modello jolly e restituisce i nomi di file e directory corrispondenti quindi sostituendo il modello jolly nel comando con gli elementi corrispondenti.

Normalmente quando lo usi **, funziona in modo simile a *, ma ricorre in modo ricorsivo a tutte le directory (come un loop).

Per vedere se è abilitato, selezionalo shopt globstar(negli script, usa shopt -q globstar).

L'esempio **.pyfunzionerebbe solo per la directory corrente, in quanto non restituisce un elenco di directory che possono essere reclutate, quindi è necessario utilizzare più caratteri jolly a livello di directory **/*.py, in modo che possano andare più in profondità.

Si prega di trovare su SO alcuni test di sintassi che ho fatto per trovare tutti i file in modo ricorsivo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.