Se filelist.txt
ha un unico nome di file per linea:
find /dir | grep -f <(sed 's@^@/@; s/$/$/; s/\([\.[\*]\|\]\)/\\\1/g' filelist.txt)
(L'opzione -f
significa che le ricerche di grep per tutti i modelli presenti nel file specificato.)
Spiegazione di <(sed '[email protected]^@/@; s/$/$/; s/\([\.[\*]\|\]\)/\\\1/g' filelist.txt)
:
Il <(...)
è chiamato process subsitution ed è un po 'simile a $(...)
. La situazione è equivalente a (ma usando la sostituzione di processo è più ordinato e forse un po 'più veloce):
sed '[email protected]^@/@; s/$/$/; s/\([\.[\*]\|\]\)/\\\1/g' filelist.txt > processed_filelist.txt
find /dir | grep -f processed_filelist.txt
La chiamata al sed
esegue i comandi [email protected]^@/@
, s/$/$/
e s/\([\.[\*]\|\]\)/\\\1/g
su ogni linea di filelist.txt
e li stampa. Questi comandi convertono i nomi dei file in un formato che funzionerà meglio con grep.
[email protected]^@/@
mezzo messo un /
alla prima di ogni nome di file. (Il ^
significa "inizio della linea" in un'espressione regolare)
s/$/$/
significa mettere uno $
alla fine di ogni nome file. (Il primo $
significa "fine riga", il secondo è solo un valore letterale $
che viene quindi interpretato da grep per "fine riga").
La combinazione di queste due regole significa che grep cercherà solo per le partite come .../<filename>
, in modo che a.txt
non corrisponde ./a.txt.backup
o ./abba.txt
.
s/\([\.[\*]\|\]\)/\\\1/g
mette un \
prima di ogni occorrenza di .
[
]
o *
. Grep usa regex e quei caratteri sono considerati speciali, ma vogliamo che siano chiari, quindi dobbiamo sfuggire a loro (se non li sfuggiamo, allora un nome di file come a.txt
potrebbe corrispondere a file come abtxt
).
Ad esempio:
$ cat filelist.txt
file1.txt
file2.txt
blah[2012].txt
blah[2011].txt
lastfile
$ sed '[email protected]^@/@; s/$/$/; s/\([\.[\*]\|\]\)/\\\1/g' filelist.txt
/file1\.txt$
/file2\.txt$
/blah\[2012\]\.txt$
/blah\[2011\]\.txt$
/lastfile$
Grep quindi utilizza ogni riga di tale uscita come un pattern Mentre cerca l'uscita di find
.
Grazie! cosa significa <(sed 's @^@/@; s/$/$ /; s /\./\\//' filelist.txt ') significa? – Dagang
@Todd, ho ampliato la mia risposta :) – huon
Non dovresti fare di tutto, cercando di ricreare i pattern a livello di programmazione. È soggetto a errori e spesso ci sono alcune zone grigie o possibilità di estensioni nelle specifiche del linguaggio del pattern. In questo caso particolare, penso che sarebbe meglio usare semplicemente 'grep -F -f FILE' –