2009-12-13 16 views
20

Sono piuttosto confuso su questo. Ho bisogno di alcuni chiarimenti.Capire il comando UNIX xargs

Esempio 1:

pgrep string | xargs ps 

Esempio 2:

find . | xargs grep whatever 

Da Esempio 1, mi sembra di capire che sia in questo modo:

ricerca di una "stringa", che è parte del nome del processo in esecuzione e restituisce gli ID di processo di tutte le corrispondenze a 'xargs ps' -> che si aggiunge ps per le partite (che sono di processo-ID stessi) per ottenere lo stesso risultato:

ps <processid> 

Qualcuno può spiegare che cosa realmente xargs fa in questo caso?

Da Esempio 2, mi sembra di capire che sia in questo modo:

E 'per cercare un po' di "stringa" ricorsivamente dalla directory di lavoro corrente. Qui, come funziona esattamente 'xargs'?

Sono stato dell'opinione che "xargs" accoda ripetutamente i dati dallo standard input all''argomento 'dato a xargs (che di solito è un comando UNIX da solo). pagina man

Da xargs():

xargs legge gli elementi dalla standard input, delimitati da spazi (che può essere protetti con virgolette doppie o singole o una barra rovesciata) o ritorni a capo, e esegue la comando (l'impostazione predefinita è/bin/echo) una o più volte con qualsiasi argomento iniziale seguito da elementi letti dallo standard input. Le righe vuote sullo standard input vengono ignorate.

+0

xargs agisce come il comando "subtitution" (almeno con Bash). Trasforma i risultati multilinea (verticale) in una lista di argomenti di token (orizzontale). (Nota che potresti filtrare un po 'i risultati (usando sed per ex) prima di passarlo attraverso xargs). Plus xargs gestisce l'errore «_too much arguments_» che può essere verificato prima del kernel Linux 2.6.23 (vedere [wikipedia] (https://en.wikipedia.org/wiki/Xargs)). Ecco [un altro thread utile] (http://unix.stackexchange.com/questions/24954/when-is-xargs-needed) – Stphane

risposta

37

In generale xargs viene utilizzato come questo

prog | xargs utilità

dove prog è previsto per emettere uno o più newline/spazio separato risultati. Il trucco è che xargs no! nessarly chiama l'utilità una volta per ogni risultato, invece è divide l'elenco dei risultati in sottoliste e chiama l'utilità per ogni sottolista. Se si desidera forzare xargs a chiamare l'utilità per ogni singolo risultato, sarà necessario richiamarlo con xargs -L1.

Note che xargs vi promette che la sottolista inviato a utilità è più breve di ARG_MAX (questo è il modo evita quei temuti lista argomento per lunghi errori).È possibile ottenere il valore corrente di ARG_MAX utilizzando getconf ARG_MAX

+1

Beh, questo è qualcosa a cui potrei riferirmi, ma ora è diventato molto più confuso. Conosco il motivo principale per cui xargs è presente, ma viene contorto quando vedo che viene utilizzato per più di uno scopo (in modi diversi). – halluc1nati0n

+7

Considera questo comando "trova/etc -type d -depth 1 | xargs echo" che stampa tutte le directory nella cartella/etc (ma non le loro sottodirectory). Poiché l'eco accetta più argomenti, il risultato è una lunga riga "/ etc/dir1/etc/dir2 ...". Se invece si chiama "find/etc -type d -depth 1 | xargs -L1 echo", quindi echo viene richiamato una volta per ogni risultato, con il risultato che ogni directory da/etc viene stampata su una riga da sola. –

+0

Come passare i comandi o le opzioni all'utilità? Dite, voglio eseguire uglifyjs e specificare e stampare la cartella per l'input che arriva in xargs? http://stackoverflow.com/questions/43149786/how-to-process-files-in-nested-directories – Costa

2

xargs è normalmente utilizzato per gli argomenti di gruppo insieme in modo che non si ottengono un errore "troppi argomenti", che si verifica quando si passa un gran numero di argomenti per un comando

6
$ echo 'line1 
> line2 
> line3 
> ... 
> lineN ' | xargs cmd1 -a -b 

si tradurrà in:

$ cmd1 -a -b line1 line2 line3 ... lineN 

xargs romperà cmd1 ... in varie esecuzioni di cmd1 se il numero di linee diventa troppo grande.

xargs può essere utilizzato per molte altre attività relative al passaggio delle righe stdin come argomenti di posizione. Dai un'occhiata all'opzione capitale -P in xargs(1) per eseguire più istanze di un comando in parallelo.

1
#!/bin/sh 
#script to echo out the arguments 1 at a time! 
for a in $* 
do 
    echo $a 
done 

il comando

$sh myscript 1 2 3 4 5 

produrrà

1 
2 
3 
4 
5 

ma

$sh myscript 1 2 3 4 5 6 7 8 9 10 11 

non funziona in quanto il numero massimo di parametri viene superato (im non proprio sicuro di quello che il massimo è, ma diciamo il suo 10 per questo esempio!)

Per ovviare a questo abbiamo potuto utilizzare

#!/bin/sh 
#script to echo out the arguments 1 at a time! 
for a in $* 
do 
    echo $a | xargs echo 
done 

potremmo quindi eseguirlo come questo

$sh myscript "1 2 3 4 5" "6 7 8 9 10 11" 

e ottenere il risultato corretto dal momento che ci sono solo 2 parametri

+2

Non so quale sia il massimo, ma non è sicuramente 10. E puoi usare $ @ invece di $ *. questo non è un ottimo esempio di come usare xargs – ghostdog74

9

Un buon esempio di ciò che fa xargs è provare a ottenere checksum ordinati per ogni file in una directory usando find.

find . | cksum | sort 

restituisce solo una somma di controllo e non è chiaro per quale motivo si tratta del checksum. Non quello che vogliamo. La pipa invia lo stdout da find a stdin per cksum. Quello che cksum vuole davvero è un elenco di argomenti da riga di comando, ad es.

cksum file001.blah file002.blah file003.blah 

riporterà tre righe, una per file, con i checksum desiderati. Xargs fa il trucco magico - convertire lo stdout del programma precedente in una riga di comando temporanea e nascosta per alimentare il successivo. La riga di comando che funziona è:

find . | xargs cksum | sort 

Nota nessun tubo tra xargs e cksum.

+1

btw, questo è l'ingrediente principale nella mia ricetta per trovare i file duplicati in due o più directory, anche se i loro nomi sono diversi. – DarenW

+0

grazie per approfondimenti e l'aggiunta di verbose a xargs dà il comando in azione. trova . | xargs --verbose cksum | sort – kumar