Come usare regex con il comando find?


298

Ho alcune immagini chiamate con la stringa uuid1 generata. Ad esempio 81397018-b84a-11e0-9d2a-001b77dc0bed.jpg. Voglio scoprire tutte queste immagini usando il comando "trova":

find . -regex "[a-f0-9\-]\{36\}\.jpg".

Ma non funziona Qualcosa non va con la regex? Qualcuno potrebbe aiutarmi con questo?


7
forse cambiare il regextype. L'impostazione predefinita è Emacs Regular Expressions , qualunque cosa significhi.
padiglione,

Risposte:


349
find . -regextype sed -regex ".*/[a-f0-9\-]\{36\}\.jpg"

Si noti che è necessario specificare .*/all'inizio perché findcorrisponde all'intero percorso.

Esempio:

susam@nifty:~/so$ find . -name "*.jpg"
./foo-111.jpg
./test/81397018-b84a-11e0-9d2a-001b77dc0bed.jpg
./81397018-b84a-11e0-9d2a-001b77dc0bed.jpg
susam@nifty:~/so$ 
susam@nifty:~/so$ find . -regextype sed -regex ".*/[a-f0-9\-]\{36\}\.jpg"
./test/81397018-b84a-11e0-9d2a-001b77dc0bed.jpg
./81397018-b84a-11e0-9d2a-001b77dc0bed.jpg

La mia versione di find:

$ find --version
find (GNU findutils) 4.4.2
Copyright (C) 2007 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Eric B. Decker, James Youngman, and Kevin Dalley.
Built using GNU gnulib version e5573b1bad88bfabcda181b9e0125fb0c52b7d3b
Features enabled: D_TYPE O_NOFOLLOW(enabled) LEAF_OPTIMISATION FTS() CBO(level=0) 
susam@nifty:~/so$ 
susam@nifty:~/so$ find . -regextype foo -regex ".*/[a-f0-9\-]\{36\}\.jpg"
find: Unknown regular expression type `foo'; valid types are `findutils-default', `awk', `egrep', `ed', `emacs', `gnu-awk', `grep', `posix-awk', `posix-basic', `posix-egrep', `posix-extended', `posix-minimal-basic', `sed'.

4
@ Tom è il modo in cui regex in find funziona. Secondo la pagina man, il regex corrisponde all'intero percorso del file, directory incluse, il che significa che c'è un implicito che "^ ... $"circonda il tuo regex. Deve corrispondere all'intera riga dei risultati.
Manny D,

2
Non penso che tu abbia bisogno di /in .*/perché .*corrisponde a zero o più di (quasi) qualsiasi personaggio.
Jeff,

2
Per quelli (come me) che non hanno letto correttamente la regex per la prima volta: nota le barre rovesciate che precedono i caratteri speciali della regex, ad esempio:\{36\}
Lucas Wilson-Richter,

11
Ho avuto difficoltà a trovare l'elenco completo dei tipi di regex (la manpage non è aggiornata):valid types are 'findutils-default', 'awk', ' egrep', 'ed', 'emacs', 'gnu-awk', 'grep', 'posix-awk', 'posix-basic', 'posix-egrep', 'posix -extended', 'posix-minimal-basic', 'sed'.
Noah Sussman,

4
Assicurati di mettere la -regextypebandiera prima della -regexbandiera, altrimenti non si applica!
Christopher Orr,

84

L' -regexespressione find corrisponde al nome intero , incluso il percorso relativo dalla directory corrente. Per find .questo inizia sempre con ./, quindi qualsiasi directory.

Inoltre, si tratta di emacsespressioni regolari, che hanno regole di fuga diverse dalle solite espressioni regolari egrep.

Se questi sono tutti direttamente nella directory corrente, allora

find . -regex '\./[a-f0-9\-]\{36\}\.jpg'

dovrebbe funzionare. (Non ne sono davvero sicuro - Non riesco a far funzionare la ripetizione contata qui.) Puoi passare alle espressioni egrep -regextype posix-egrep:

find . -regextype posix-egrep -regex '\./[a-f0-9\-]{36}\.jpg'

(Nota che tutto ciò che è stato detto qui è per GNU find, non so nulla di quello BSD che è anche quello predefinito su Mac.)


1
Avevo una parentesi per più stringhe corrispondenti nella mia regex, quindi il posix-egreptipo ha funzionato per me.
Palswim,

2
Qualcosa da notare, -regextypeè un'opzione per GNU finde non per BSD (almeno non per Mac BSD) find. Se questa opzione non è disponibile, assicurati di installare GNU find. Se su un Mac è possibile con il pacchetto brew findutils. Trova è quindi disponibile tramite gfind.
DanCat,

regextype posix-egrep ha fatto il lavoro per me. Penso che il default sia regextype emacs.
Infocloggato l'

35

A giudicare dalle altre risposte, sembra che questa potrebbe essere colpa di trovare.

Tuttavia puoi farlo in questo modo invece:

find . * | grep -P "[a-f0-9\-]{36}\.jpg"

Potrebbe essere necessario modificare un po 'il grep e utilizzare diverse opzioni a seconda di ciò che si desidera, ma funziona.


Ha funzionato bene per me e offre un grande grado di libertà rispetto alla regex.
Glaucon,

3
Un aspetto negativo di questo è che non si può prendere vantaggio di find's -prunefunzionalità che saltare alcune directory del tutto. Molto spesso questo non è molto importante, ma vale la pena menzionarlo.
Alexander Bird,

-prune funzionerà ancora, immagino. Sarebbe più pericoloso usare -exec: funzionerebbe su tutti i file e non solo su quelli che grep permette di passare.
tpb261,

13

su Mac OS X (BSD find) : uguale alla risposta accettata, il .*/prefisso è necessario per abbinare un percorso completo:

$ find -E . -regex ".*/[a-f0-9\-]{36}.jpg"

man finddice che -Eusa il supporto regex esteso


Sembra -Enon disponibile su Ubuntu (testato su Ubuntu WSL)
Warlike Chimpanzee

2
@Clever Little Monkey - No, la risposta accettata dovrebbe funzionare su Ubuntu, questa variazione è specifica per Mac OS X (o forse un'altra variante di BSD come FreeBSD)
Stan Kurdziel,

8

Prova a usare le virgolette singole (') per evitare l'escape della shell dalla tua stringa. Ricorda che l'espressione deve corrispondere all'intero percorso, ovvero deve apparire come:

 find . -regex '\./[a-f0-9-]*.jpg'

A parte questo, sembra che la mia ricerca (GNU 4.4.2) conosca solo espressioni regolari di base, specialmente non la sintassi {36}. Penso che dovrai farne a meno.


8

Modo semplice: è possibile specificare. * All'inizio perché find corrisponde all'intero percorso.

$ find . -regextype egrep -regex '.*[a-f0-9\-]{36}\.jpg$'

trova versione

$ find --version
find (GNU findutils) 4.6.0
Copyright (C) 2015 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 
<http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Eric B. Decker, James Youngman, and Kevin Dalley.
Features enabled: D_TYPE O_NOFOLLOW(enabled) LEAF_OPTIMISATION 
FTS(FTS_CWDFD) CBO(level=2)

6

È necessario utilizzare il percorso di directory assoluto quando si applicano le istruzioni find con espressione regolare. Nel tuo esempio, il

find . -regex "[a-f0-9\-]\{36\}\.jpg"

dovrebbe essere cambiato in

find . -regex "./[a-f0-9\-]\{36\}\.jpg"

Nella maggior parte dei sistemi Linux, alcune discipline in espressione regolare non possono essere riconosciute da quel sistema, quindi è necessario indicare esplicitamente -regexty come

find . -regextype posix-extended -regex "[a-f0-9\-]\{36\}\.jpg"
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.