Glob recursiv? (Unix, Bash, Shell, Wildcards, Recursiv)

Paolo a intrebat.
a intrebat.

Aș dori să scriu ceva de genul acesta:

$ ls **.py

pentru a obține toate numele de fișiere .py, parcurgând recursiv o ierarhie de directoare.

Chiar dacă există fișiere .py de găsit, shell-ul (bash) dă această ieșire:

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

Există vreo modalitate de a face ceea ce vreau eu?

EDIT: Aș dori să precizez că nu sunt interesat de cazul specific al ls, , ci întrebarea se referă la sintaxa glob.

3 răspunsuri
jordanm

Pentru a putea face globi recursivi în bash, aveți nevoie de globstar caracteristică de la versiunea 4 sau mai mare a bash-ului.

Din pagina de manual 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.

Pentru modelul dvs. de exemplu:

shopt -s globstar
ls -d -- **/*.py

Comentarii

  • Aș recomanda, de asemenea, activarea nullglob –  > Por glenn jackman.
  • @glennjackman Dar înainte de a activa nullglob, , aș recomanda cu tărie să citiți următoarele avertismente. –  > Por Serge Stroobandt.
  • ^ Avertismentele au fost mutate aici. –  > Por rgajrawala.
  • Cu bash 3.2, wc -l {**,.}/*.py funcționează foarte bine –  > Por Raphael.
  • @Raphael Am verificat de două ori notele de lansare și se spune cu siguranță că a fost introdusă în 4.0. Poate că distribuția dvs. a backportat un patch pentru aceasta? IIRC RHEL 5 a retroportat unele caracteristici. De asemenea, este de remarcat că au trecut 9 ani de când a fost lansat bash 4… –  > Por jordanm.
doneal24
find . -name '*.py'

** nu face nimic mai mult decât un singur *, ambele operează în directorul curent

Comentarii

  • Interesant. Deși, mă concentrez mai mult pe sintaxa glob prin ea însăși, deoarece trebuie să o folosesc într-un fișier de configurare (directiva include). Nu am nevoie de o listă de fișiere. –  > Por Paolo.
  • @Doug O’Neal, acest lucru nu mai este adevărat. bash a copiat acum această caracteristică zsh (deși a adoptat o sintaxă mai apropiată de cea din ksh93 și, la fel ca și ksh, nu suportă încă calificativele de globbing ale lui zsh, ceea ce îi limitează utilitatea) – -.  > Por Stéphane Chazelas.
  • Există o mulțime de lucruri pe care le puteți face cu find dacă nu aveți bash 4. Exemple: yourcommand `find . -name '*.py'` (observați ghilimelele de subsol); find . -name '*.py' -exec yourcommand {} ;. –  > Por Mars.
kenorb

De la Bash 4 (inclusiv zsh) o nouă opțiune de globbing (globstar) a fost adăugată care tratează modelul ** în mod diferit atunci când este setată.

Aceasta se potrivește cu modelul wildcard și returnează numele fișierelor și directoarelor care se potrivesc atunci, înlocuind modelul wildcard din comandă cu elementele potrivite.

În mod normal, atunci când utilizați **, funcționează în mod similar cu *, , dar parcurge toate directoarele în mod recursiv (ca o buclă).

Pentru a vedea dacă este activat, verificați dacă este activat prin shopt globstar (în scripting, utilizați shopt -q globstar).

Exemplul **.py ar funcționa numai pentru directorul curent, deoarece nu returnează o listă de directoare care pot fi recursate, de aceea trebuie să folosiți mai multe wildcard-uri la nivel de director. **/*.py, , astfel încât să poată merge mai departe.

Vedeți aici exemple de căutare recursivă a fișierelor.

Comentarii

  • Vă mulțumim! Globstar poate fi activat prin shopt -s globstar. –  > Por Ladislav Ondris.