Sto cercando una dichiarazione di classe su un sito con centinaia di file PHP. Come posso farlo nella cartella e nelle sottocartelle correnti usando grep ?
Ho provato cd
la cartella e quindi qualcosa di simile
grep -r 'class MyClass' *.php
Sto cercando una dichiarazione di classe su un sito con centinaia di file PHP. Come posso farlo nella cartella e nelle sottocartelle correnti usando grep ?
Ho provato cd
la cartella e quindi qualcosa di simile
grep -r 'class MyClass' *.php
Risposte:
Puoi provare
grep -r --include=*.php "search string" /path/to/dir
Ti consiglierei di usare qualcosa come i tag piuttosto che farlo con un grep. Tuttavia, se vuoi, puoi fare qualcosa del genere
find <top level dir> -name \*.php | xargs grep "class MyClass"
Questo ovviamente presuppone che tu abbia un solo spazio tra class
e myClass
che potrebbe non essere vero. È facile cambiare la regexp per cercare un numero qualsiasi di spazi bianchi.
Se lo usi -r
, probabilmente vorrai cercare ricorsivamente solo la directory corrente :
grep -r 'class MyClass' .
Nota il periodo alla fine di quanto sopra.
Quello che hai detto grep
è che volevi che cercasse in modo ricorsivo ogni *.php
file o directory , ma probabilmente non avevi alcuna directory che terminasse con un'estensione .php. Quanto sopra è il modo più semplice possibile per eseguire la ricerca, ma include anche file di altri tipi, il che è particolarmente problematico quando si hanno directory .svn ovunque. Se non hai molti altri tipi di file, quanto sopra è generalmente sufficiente e funziona bene.
La maggior parte delle incarnazioni di grep non ha un modo per specificare le estensioni dei file che possono essere ricercate, quindi generalmente si usa find insieme ad esso:
find <startDir> -iname '*.php' -exec grep 'class[ \t]*MyClass' {} \;
-iname
dice ad alcune versioni di grep che si desidera effettuare una ricerca di nomi di file senza distinzione tra maiuscole e minuscole, ma molte delle varianti non GNU di find non lo supportano, quindi è possibile utilizzare -name
invece.
L' -exec
opzione sopra ha l'effetto collaterale di invocare grep per ogni file, il che è abbastanza costoso.
Altre versioni di grep supportano a +
che dice find di aggiungere gli argomenti insieme per ridurre il numero di invocazioni dell'eseguibile:
find <startDir> -iname '*.php' -exec grep 'class[ \t]*MyClass' {} + \;
Un modo frequentemente raccomandato per ridurre le invocazioni è usare xargs che lanceranno grep il meno volte possibile ma quante volte necessario:
find <startDir> -iname \*.php | xargs grep "class[ \t]*MyClass"
xargs
è abbastanza intelligente da passare grep fino al numero massimo di argomenti supportati sulla riga di comando, ma la variazione sopra non gestisce molto bene alcuni caratteri come gli spazi. Ad esempio, se "file.php" un nome file grep ricevesse "the" come argomento e "file.php" come argomento, in modo che entrambi non vengano trovati. Invece usiamo:
find <startDir> -iname \*.php -print0 | xargs -0 grep "class[ \t]*MyClass"
print0
e -0
lavorare insieme e utilizzare argomenti seguiti da un carattere null in modo che l'argomento sia identificato in modo completo e inequivocabile.
Se hai mai più di uno spazio dopo class
, o una scheda, potresti voler consentire più caratteri modificando la regex:class[ \t]*MyClass
Questo post su StackOverflow contiene altri esempi e mostra come escludere determinate directory, come le directory .svn.
grep -r 'class MyClass' *.php
cercherà in tutte le cartelle con nomi che finiscono con .php
grep -r 'class MyClass' . | grep .php
cercherà la classe MyClass in tutti i file in tutte le sottocartelle, quindi restituirà solo quelli che contengono .php.
find . -type f -name *.php -print -exec grep \"class MyClass\" {} \;
ti fornirà il contenuto della riga su cui si trova e il percorso del file.
Probabilmente vuoi l'insensibilità al maiuscolo / minuscolo e la tolleranza agli spazi bianchi e grep terminerà se non trova alcuna istanza del modello di file desiderato nella directory corrente. Deve sapere da dove cominciare, per così dire, e nessun file abbinato non produce alcun percorso iniziale.
Se è presente almeno un file dell'estensione desiderata, è possibile utilizzare egrep -ir. find
e xargs
mostrano la loro potenza con singole directory flat (ma molto grandi) su cui grep fallisce e qualificatori extra (ad esempio se si desidera cercare solo file .inc, .php e php3). Ma nella mia esperienza perde un po 'di praticità e velocità. Per le dichiarazioni di classi scritte umane un grosso problema sarà lo spazio bianco. Quindi usa egrep invece di grep. Anche LC_ALL = C per una maggiore velocità. Per comodità, utilizzo spesso:
LC_ALL=C egrep -irn "class[ ]*myclass([ ]|\n)" * | egrep "\.(inc|php[35]?)"
-i -- case insensitive
-r -- recursive for all file pattern (here *)
-n -- include the line number
LC_ALL=C -- search in ASCII, not in utf8, this is much faster.
[ ]* -- match any number of spaces before the class name
([ ]|\n) -- match a space or newline after the classname
Questo può ancora abbinare i commenti, come // class myclass exists in file
, ma trovo che siano relativamente piccoli e possono essere filtrati... | fgrep -v '//'
Puoi anche includere maschere di file più complesse (ad esempio, per catturare la maggior parte dei file .inc e .php) sul modello di file egrep in questo modo:
egrep "pattern" *.[ip]*
Quello (con le prime opzioni) sarà abbastanza veloce e per lo più limitato ai file php.
HTH
So che dice di usare grep
, ma il mio preferito è usare ack-grep
:
ack-grep "class MyClass"
Viene eseguito in modo ricorsivo, elenca il nome del file in cui trova i risultati, con i numeri di riga per la posizione in cui si trovano e mette in evidenza. Per indirizzare in modo specifico i file php è possibile eseguire:
ack-grep --type-set php:ext:php "path"
Il pacchetto ha molte opzioni; Lo consiglio vivamente (e navigando nella sua pagina man associata) per fare cose fantasiose.
grep -r
non ti ha dato.