2013-08-07 13 views
23

Ho alcuni file, comeCirca l'utilizzo di comando di Linux "xargs"

love.txt 
loveyou.txt 

nella directory useful; Voglio copiare questo file nella directory /tmp.

Io uso questo comando:

find ./useful/ -name "love*" | xargs cp /tmp/ 

ma non funziona, dice solo:

cp: target `./useful/loveyou.txt' is not a directory 

quando uso questo comando:

find ./useful/ -name "love*" | xargs -i cp {} /tmp/ 

funziona benissimo,

Voglio sapere w il secondo funziona e altro sull'uso di -i cp {}.

+2

cosa c'è di sbagliato con 'cp ./useful/love*/tmp /'? – sehe

+2

Questo _will_ funziona con GNU cp senza '-i', in questo modo:' find ./useful/ -name "love *" -print0 | xargs -0 cp -t/tmp' –

+2

... si noti che l'uso di xargs senza '-0' è pericoloso, perché separa i nomi di file con newline, ma una newline è un carattere valido all'interno dei nomi di file su UNIX. –

risposta

19

xargs inserisce le parole provenienti dallo standard input alla fine dell'elenco di argomenti del comando specificato. Il primo modulo pertanto crea

cp /tmp/ ./useful/love.txt ./useful/loveyou.txt 

Quale non funziona, perché ci sono più di 2 argomenti e l'ultimo non è una directory.

L'opzione -i dice xargs per elaborare un file alla volta, però, la sostituzione {} con il suo nome, in modo che è equivalente a

cp ./useful/love.txt /tmp/ 
cp ./useful/loveyou.txt /tmp/ 

Quali opere chiaramente ben.

4

Il primo esempio farà questo:

cp /tmp/ love.txt loveyou.txt 

Il che non può essere fatto, dal momento che tentano di copiare la directory /tmp e il file love.txt al file loveyou.txt.

Nel secondo esempio, -i dice xargs per sostituire ogni istanza di {} con l'argomento, in modo che farà:

cp love.txt /tmp/ 
cp loveyou.txt /tmp/ 
+2

quando si esegue senza -i, il comando cp verrà eseguito solo una volta con tutti gli argomenti passati come lista, no? per esempio. provalo usando 'echo' –

+0

@GrahamGriffiths: hai ragione. Stavo pensando all'esempio di 'xargs -n 1'. Correggerò questo –

10

Quando si utilizza il comando xargs -i, {} è sostituito con ogni elemento si trova. Quindi, nel tuo caso, sia per "loveyou.txt" e "love.txt", il seguente comando verrà eseguito:

cp ./useful/loveyou.txt /tmp/ 
cp ./useful/love.txt /tmp/ 

se si omette il {}, tutti gli elementi che si trovano sarà automaticamente inserita alla la fine del comando, così, si eseguirà il comando senza senso:

cp /tmp/ ./useful/loveyou.txt ./useful/love.txt 
+2

durante l'esecuzione senza -i, il comando cp verrà eseguito solo una volta con tutti gli argomenti passati come elenco, no? per esempio. provalo usando 'echo' –

+0

@GrahamGriffiths Hai assolutamente ragione. Risposta aggiornata di conseguenza. Può essere dimostrato se si esegue il piping a 'xargs echo AAA'. –

4

xargs aggiunge i valori qui inseriti come un flusso alla fine del comando - non viene eseguito il comando una volta per ogni valore di ingresso. Se vuoi che lo stesso comando venga eseguito più volte, ecco a cosa serve la sintassi -i cp {}.

Questo funziona bene per i comandi che accettano un elenco di argomenti alla fine (ad es. Grep) - sfortunatamente cp non è uno di quelli - considera gli argomenti passati come directory da copiare, il che spiega che 'non è un errore di directory '.

1

Si potrebbe evitare di xargs in questo modo:

find ./useful/ -name "love*" -exec sh -c 'cp "[email protected]" /tmp' sh {} + 
3
find ./useful/ -name "love*" | xargs cp -t /tmp/ 
+0

-i [replace-str] Questa opzione è un sinonimo di -Ireplace-str se replace-str è specificato, e per -I {} in caso contrario. Questa opzione è deprecata; usa -I invece. – user3581131

+1

bene, ma devi modificare la tua domanda e metterla lì, altrimenti i voti bloccati non possono essere modificati. – maraca