Sono consapevole che -exec
può accettare unopzione +
per imitare il comportamento di xargs
. Cè qualche situazione in cui “preferiresti un form rispetto allaltro?
Personalmente tendo a preferire il primo form, anche solo per evitare di usare una pipe. Immagino sicuramente gli sviluppatori di find
deve” aver eseguito le ottimizzazioni appropriate. Ho ragione?
Risposta
Potresti voler concatenare le chiamate per trovare (una volta, quando hai imparato, che è possibile , che potrebbe essere oggi). Questo è, ovviamente, possibile solo finché rimani in find. Una volta eseguito il pipe a xargs, è fuori ambito.
Piccolo esempio, due file a.lst e b.lst:
cat a.lst fuddel.sh fiddel.sh cat b.lst fuddel.sh
Nessun trucco qui – semplicemente il fatto che entrambi contengono “fuddel” ma solo uno contiene “fiddel”.
Supponiamo che non lo sapessimo. Cerchiamo un file che soddisfi 2 condizioni:
find -exec grep -q fuddel {} ";" -exec grep -q fiddel {} ";" -ls 192097 4 -rw-r--r-- 1 stefan stefan 20 Jun 27 17:05 ./a.lst
Beh, forse conosci la sintassi per grep o un altro programma per passare entrambe le stringhe come condizione, ma quella ” Non è questo il punto. Ogni programma che può restituire vero o falso, dato un file come argomento, può essere usato qui – grep era solo un esempio popolare.
E nota, puoi seguire find -exec con altri comandi di ricerca, come -ls o -delete o qualcosa di simile. Nota che leliminazione non solo rm (rimuove i file), ma rmdir (rimuove anche le directory).
Tale catena viene letta come una combinazione AND di comandi, purché non diversamente specificato (vale a dire con un -or
opzione (e parens (che devono essere mascherati))).
Quindi non stai lasciando la catena di ricerca, che è una cosa utile. Non vedo alcun vantaggio nellusare -xargs, dal momento che devi stare attento nel passare i file, cosa che find non ha bisogno di fare – gestisce automaticamente il passaggio di ogni file come un singolo argomento per te.
Se ritieni di aver bisogno di mascherare le {} parentesi graffe , sentiti libero di visitare la mia domanda che richiede prove. La mia affermazione è: tu non “t.
Commenti
- Questo post mi ha aperto gli occhi su un nuovo modo di usare
find
. Grazie mille! - ” Non ‘ non vedo alcun vantaggio nellutilizzo -xargs “. Che ‘ è
-exec
modo di farexargs -P4
in modo che tre dei quattro core non ‘ rimangano inattivi? - @DamianYerrick: Termina il comando -exec non in “; ” ma con un segno + (/ più).
Risposta
Per trasferire in modo sicuro i nomi dei file a xargs
è necessario che il tuo find
supporti -print0
e il tuo xargs
ha lopzione corrispondente per leggerlo (--null
o -0
). In caso contrario, i nomi dei file con unprintab i caratteri, le barre rovesciate o le virgolette o gli spazi bianchi nel nome possono causare un comportamento imprevisto. Daltro canto, find -exec {} +
è nella POSIX find
specifica , quindi è portabile ed è sicuro quanto find -print0 | xargs -0
e decisamente più sicuro di find | xargs
. “Consiglio mai di fare find | xargs
senza -print0
.
Commenti
Risposta
Se utilizzi il modulo -exec ... ;
(ricordando per evitare il punto e virgola), stai eseguendo il comando una volta per nome di file. Se utilizzi -print0 | xargs -0
, esegui più comandi per nome di file. Dovresti assolutamente utilizzare -exec +
, che inserisce più file in una singola riga di comando ed è molto più veloce quando è coinvolto un gran numero di file.
Un grande vantaggio nellusare xargs
è la capacità di eseguire più comandi in parallelo utilizzando xargs -P
. Sui sistemi multi-core, ciò può fornire un enorme risparmio di tempo.
Commenti
- Volevi dire
-P
invece di-p
. Tieni presente chexargs -P
non fa parte dello standard POSIX, mentrefind -exec {} +
lo è, che è importante se stai cercando la portabilità. - @Alexios Non ‘ devi evitare il segno più, perché non ha un significato speciale per la shell:
find /tmp/ -exec ls "{}" +
funziona perfettamente. - Corrent, ovviamente. ‘ sono scappato da tutto dopo
-exec
per così tanto tempo (sono ‘ un masochista , Non ‘ uso nemmeno le virgolette per sfuggire a{}
, digito sempre\{\}
; don ‘ t ask), sembra che tutto debba essere scappato ora. - @Alexios: se trovi un esempio (tranne che per essere un masochista) il mascheramento delle parentesi graffe è utile, forniscilo come risposta alla mia domanda qui – anche se questo suggerimento è obsoleto e solo un relitto nella pagina di manuale. ‘ non ho mai visto un esempio in cui
find /tmp/ -exec ls {} +
‘ non funzionerebbe. - Per me, questa è la memoria muscolare che si è formata ai tempi di SunOS 4. Da quando ‘ lo faccio da anni, non sono riuscito a notarlo
bash
ha iniziato ad accettare le parentesi graffe alla lettera. ‘ sono abbastanza sicuro che almeno una delle vecchie conchiglie che ‘ abbia usato sibilando se le parentesi graffe non fossero ‘ t sfuggito.
Risposta
Per quanto riguarda le prestazioni, ho pensato che -exec … +
sarebbe semplicemente migliore perché “è un unico strumento che fa tutto il lavoro ma una parte della documentazione di GNU findutil dice che -exec … +
potrebbe essere meno efficiente in alcuni casi:
[trova con
-exec … +
] può essere meno efficiente di alcuni usi dixargs
; ad esempioxargs
consente di creare nuove righe di comando mentre il comando precedente è ancora in esecuzione e consente di specificare un numero di comandi da eseguire in parallelo. Tuttavia, il costruttofind ... -exec ... +
ha il vantaggio di unampia portabilità. Findutils GNU non supportava “-exec ... +
” fino alla versione 4.2.12 [gennaio 2005] ; uno dei motivi è che in ogni caso aveva già lazione “-print0
“.
Non ero “esattamente sicuro di cosa volesse dire, quindi ho chiesto nella chat dove derobert lo ha spiegato come:
find
probabilmente potrebbe continuare a cercare il gruppo di file successivo mentre il-exec … +
è in esecuzione, ma non “t.
find … | xargs …
lo fa, perché in tal caso la ricerca è un processo diverso e mantiene in esecuzione finché il buffer della pipe non si riempie
(Formattazione da me.)
Quindi è così. Ma se le prestazioni sono davvero importanti, dovresti fare benchmark realistici o piuttosto chiederti se vorresti usare la shell per questi casi.
Qui su questo sito penso che sia meglio consigliare alle persone di usa il modulo -exec … +
ogni volta che è possibile perché solo perché è più semplice e per i motivi menzionati nelle altre risposte qui (ad esempio, gestire strani nomi di file senza dover pensare molto).
find … -exec … {} +
è OpenBSD, che ha acquisito questa funzionalità solo con la versione 5.1 rilasciata nel 2012. Tutti i BSD hanno avuto-print0
per diversi anni, anche OpenBSD (anche se ha resistito a quella funzione per un po ). Solaris, invece, si attacca alle funzionalità POSIX, quindi ottieni-exec +
e nessun-print0
.-print0
è una seccatura e anche se puoi discuterexargs --delimiter "\n"
non è ‘ t equivalente, ‘ non ho mai usato il primo dopo aver scoperto il secondo .-0
sia più doloroso di--delimiter "\n"
.-0
, GNUxargs
necessita di-r
per evitare di eseguire il comando se ‘ non ha input.| xargs -r0 cmd
è checmd
‘ s stdin è interessato (a seconda dellimplementazionexargs
, ‘ s/dev/null
o pipe.