Differenza tra "xargs" e sostituzione dei comandi?


14

In molti casi utilizzo la sostituzione dei comandi anziché xargs. Ad esempio rm $(ls)è lo stessols | xargs rm

Quali sono veramente le differenze tra loro?

Penso che una delle differenze sia che la sostituzione dei comandi viene eseguita in subshell mentre xargsviene eseguita nella shell corrente ma non ne sono sicuro.

Si prega di elencare le differenze.

Risposte:


9

Una differenza è che quando si utilizza la sostituzione dei comandi anziché una pipe, la dimensione dei dati passati è limitata dalla dimensione del buffer dei comandi, quindi in alcuni casi viene troncata senza preavviso. Ciò significa anche che l'intero output del comando deve essere prodotto e archiviato in memoria, prima di essere passato al comando successivo, quindi per output di grandi dimensioni è possibile utilizzare molta più memoria del necessario.

Un altro problema con il primo metodo è che l'output è suddiviso su spazi bianchi, quindi non è possibile gestire nomi di file con spazi all'interno. xargsinoltre è interessato dal problema degli spazi bianchi, ma può essere risolto modificando il delimitatore utilizzato. Per gestire correttamente i nomi dei file, è necessario utilizzare il byte null come delimitatore nel secondo esempio.

Un terzo problema è che i globs sono espansi, quindi se un file ha asterischi o punti interrogativi nel suo nome, ci saranno risultati imprevisti.

Puoi trovare una bella discussione sull'argomento qui: http://mywiki.wooledge.org/ParsingLs

La sintassi corretta sarebbe

echo rm *

o se devi usare xargs,

find . -maxdepth 1 -print0 | xargs -0 echo rm

Rimuovere echoquando l'output sembra corretto.


1
@Sinoosh: xargsfunziona anche in una subshell a causa della pipe, a meno che tu non lo abiliti shopt -s lastpipe, nel qual caso verrà eseguita nella shell corrente. Non penso che l'esecuzione in una subshell sia un problema, in questo caso, poiché non si modificano variabili.
user000001

1
@Sinoosh: per passare gli argomenti uno a uno puoi usare il -lflag, come find . -maxdepth 1 -print0 | xargs -0 -l rm. Per la seconda domanda, non è possibile utilizzare lscon xargs -0quanto ls non divide l'uscita sul Bute nulla, ma con a capo (che sono validi nei nomi dei file BTW)
user000001

1
@Sinoosh: non il primo paragrafo, ma il secondo: xargs senza l' -0opzione soffre del problema degli spazi bianchi.
user000001

1
Leggi man xargs, usa echoper i test, no rm. xargsci consente di superare i limiti della shell (alcuni buffer sono limitati a 65 KB, un elenco di nomi di file non lo è).
Waltinator,

1
@Sinoosh: non ho un buon riferimento a portata di mano, ma puoi digitare xargs --show-limitse vedrai il limite impostato sul tuo sistema,
user000001
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.