Il Linux find
comando è ottimo per cercare file e directory. Ma puoi anche passare i risultati della ricerca ad altri programmi per un’ulteriore elaborazione. Ti mostriamo come.
Il comando trova Linux
Il Linux find
il comando è potente e flessibile. Può cercare file e directory utilizzando un’intera serie di criteri diversi, non solo nomi di file. Ad esempio, può cercare file vuoti, file eseguibili o file di proprietà di un particolare utente. Può trovare ed elencare i file in base ai tempi di accesso o modifica, puoi usare modelli regex, è ricorsivo per impostazione predefinita e funziona con pseudo-file come named pipe (buffer FIFO).
Tutto ciò è straordinariamente utile. L’umile find
comando racchiude davvero un po’ di potenza. Ma c’è un modo per sfruttare quel potere e portare le cose a un altro livello. Se possiamo prendere l’output di find
comando e usarlo automaticamente come input di altri comandi, possiamo fare in modo che accada qualcosa ai file e alle directory che trovano scoperte per noi.
Il principio di reindirizzare l’output di un comando in un altro comando è una caratteristica fondamentale dei sistemi operativi derivati da Unix. Il principio di progettazione di fare in modo che un programma faccia una cosa e la faccia bene, e aspettarsi che il suo output possa essere l’input di un altro programma, anche un programma non ancora scritto, è spesso descritto come la “filosofia Unix”. Eppure alcune utilità di base, come mkdir
, non accettare l’input tramite pipe.
Per ovviare a questa carenza il xargs
comando può essere utilizzato per suddividere l’input convogliato e per inserirlo in altri comandi come se fossero parametri della riga di comando per quel comando. Questo ottiene quasi la stessa cosa di una semplice tubazione. Questa è “quasi la stessa cosa” e non “esattamente la stessa cosa” perché possono esserci differenze inaspettate con le espansioni della shell e il globbing dei nomi dei file.
Usando trova con xargs
Possiamo usare find
con xargs
ad alcune azioni eseguite sui file trovati. Questo è un modo prolisso per farlo, ma potremmo alimentare i file trovati da find
in xargs
, che poi li convoglia tar
per creare un file di archivio di tali file. Eseguiremo questo comando in una directory che contiene molti file PAGE del sistema della guida.
find ./ -name "*.page" -type f -print0 | xargs -0 tar -cvzf page_files.tar.gz
Il comando è composto da diversi elementi.
-
trova ./ -nome “*.pagina” -digita f -stampa0: L’azione di ricerca verrà avviata nella directory corrente, cercando per nome i file che corrispondono alla stringa di ricerca “*.page”. Le directory non verranno elencate perché gli stiamo specificando di cercare solo i file, con
-type f
. Ilprint0
l’argomento dicefind
per non trattare gli spazi bianchi come la fine di un nome file. Ciò significa che i nomi di file con spazi al loro interno verranno elaborati correttamente. -
xargs -o: Il
-0
argomentixargs
per non trattare gli spazi bianchi come la fine di un nome file. -
tar -cvzf page_files.tar.gz: Questo è il comando
xargs
alimenterà l’elenco dei file dafind
a. L’utilità tar creerà un file di archivio chiamato “page_files.tar.gz”.
Possiamo usare ls
per vedere il file di archivio creato per noi.
ls *.gz
Il file di archivio viene creato per noi. Affinché ciò funzioni, è necessario passare tutti i nomi di file tar
in massa, che è quello che è successo. Tutti i nomi dei file sono stati taggati alla fine del file tar
comando come una riga di comando molto lunga.
Puoi scegliere di eseguire il comando finale su tutti i nomi di file contemporaneamente o richiamato una volta per nome di file. Possiamo vedere la differenza abbastanza facilmente collegando l’output da xargs
all’utilità di conteggio delle righe e dei caratteri wc
.
Questo comando convoglia tutti i nomi di file in wc
subito. Effettivamente, xargs
costruisce una lunga riga di comando per wc
con ciascuno dei nomi di file in esso contenuti.
find . -name "*.page" -type f -print0 | xargs -0 wc
Vengono stampate le righe, le parole ei caratteri di ciascun file, insieme al totale di tutti i file.
Se usiamo xarg
‘S -I
(sostituisci stringa) e definisci un token di stringa sostitutivo, in questo caso ” {}
“—il token viene sostituito nel comando finale da ciascun nome di file a turno. Questo significa wc
viene chiamato ripetutamente, una volta per ogni file.
find . -name "*.page" -type f -print0 | xargs -0 -I "{}" wc "{}"
L’uscita non è ben allineata. Ogni invocazione di wc
opera su un unico file così wc
non ha nulla con cui allineare l’output. Ogni riga di output è una riga di testo indipendente.
Perché wc
può fornire un totale solo quando opera su più file contemporaneamente, non otteniamo le statistiche di riepilogo.
L’opzione find -exec
Il find
comando ha un metodo integrato per chiamare programmi esterni per eseguire ulteriori elaborazioni sui nomi di file che restituisce. Il -exec
L’opzione (execute) ha una sintassi simile ma diversa da quella xargs
comando.
find . -name "*.page" -type f -exec wc -c "{}" ;
Questo conterà le parole nei file corrispondenti. Il comando è composto da questi elementi.
-
trovare .: avvia la ricerca nella directory corrente. Il
find
il comando è ricorsivo per impostazione predefinita, quindi verranno cercate anche le sottodirectory. - -nome “*.pagina”: Stiamo cercando file con nomi che corrispondono alla stringa di ricerca “*.page”.
- -tipo f: Cerchiamo solo file, non directory.
-
-exec wc: Stiamo per eseguire il
wc
comando sui nomi di file che corrispondono alla stringa di ricerca. - -w: Qualsiasi opzione che si desidera passare al comando deve essere posizionata immediatamente dopo il comando.
- “{}”: Il segnaposto “{}” rappresenta ogni nome di file e deve essere l’ultimo elemento nell’elenco dei parametri.
- ;: un punto e virgola “;” viene utilizzato per indicare la fine dell’elenco dei parametri. Deve essere sottoposto a escape con una barra rovesciata “” in modo che la shell non lo interpreti.
Quando eseguiamo quel comando, vediamo l’output di wc
. Il -c
(conteggio byte) limita il suo output al numero di byte in ciascun file.
Come puoi vedere non c’è il totale. Il wc
il comando viene eseguito una volta per nome file. Sostituendo un segno più “+
” per il punto e virgola finale “;
” possiamo cambiare -exec
comportamento di operare su tutti i file contemporaneamente.
find . -name "*.page" -type f -exec wc -c "{}" +
Otteniamo il totale di riepilogo e risultati ordinatamente tabulati che ci dicono che tutti i file sono stati passati wc
come una lunga riga di comando.
exec Significa davvero exec
Il -exec
L’opzione (execute) non avvia il comando eseguendolo nella shell corrente. Utilizza l’exec integrato di Linux per eseguire il comando, sostituendo il processo corrente, la tua shell, con il comando. Quindi il comando che viene lanciato non è affatto in esecuzione in una shell. Senza una shell, non puoi ottenere l’espansione della shell dei caratteri jolly e non hai accesso agli alias e alle funzioni della shell.
Questo computer ha una funzione di shell definita chiamata words-only
. Questo conta solo le parole in un file.
function words-only () { wc -w $1 }
Forse una strana funzione, “solo parole” è molto più lungo da digitare di “wc -w”, ma almeno significa che non è necessario ricordare le opzioni della riga di comando per wc
. Possiamo testare cosa fa in questo modo:
words-only user_commands.pages
Funziona bene con una normale chiamata da riga di comando. Se proviamo a invocare quella funzione usando find
‘S -exec
opzione, fallirà.
find . -name "*.page" -type f -exec words-only "{}" ;
Il find
comando non riesce a trovare la funzione shell e il -exec
l’azione fallisce.
Per superare questo possiamo avere find
avvia una shell Bash e passa il resto della riga di comando ad essa come argomenti per la shell. Dobbiamo racchiudere la riga di comando tra virgolette doppie. Ciò significa che dobbiamo sfuggire alle virgolette doppie che si trovano intorno al “{}
” sostituire la stringa.
Prima di poter eseguire il find
comando, dobbiamo esportare la nostra funzione di shell con il -f
(come una funzione) opzione:
export -f words-only
find . -name "*.page" -type f -exec bash -c "words-only "{}"" ;
Funziona come previsto.
Utilizzo del nome file più di una volta
Se vuoi concatenare più comandi insieme puoi farlo, e puoi usare il “{}
” sostituire la stringa in ogni comando.
find . -name "*.page" -type f -exec bash -c "basename "{}" && words-only "{}"" ;
Se noi cd
salire di livello fuori dalla directory “pagine” ed eseguire quel comando, find
scoprirà comunque i file PAGE perché esegue la ricerca in modo ricorsivo. Il nome del file e il percorso vengono passati al nostro words-only
funzionare come prima. Puramente per motivi di dimostrazione dell’utilizzo -exec
con due comandi, chiamiamo anche il basename
comando per vedere il nome del file senza il suo percorso.
Sia il basename
comando e il words-only
funzione shell hanno i nomi dei file passati loro usando un “{}
” sostituire la stringa.
Cavalli per Corsi
C’è un carico della CPU e una penalità di tempo per chiamare ripetutamente un comando quando potresti chiamarlo una volta e passargli tutti i nomi di file in una volta sola. E se stai invocando una nuova shell ogni volta per avviare il comando, l’overhead peggiora.
Ma a volte, a seconda di ciò che stai cercando di ottenere, potresti non avere un’altra opzione. Qualunque sia il metodo richiesto dalla tua situazione, nessuno dovrebbe essere sorpreso dal fatto che Linux fornisca opzioni sufficienti per trovare quella adatta alle tue esigenze particolari.