GNU/Linux >> Linux Esercitazione >  >> Linux

Come passare l'output del comando come più argomenti a un altro comando

Per completezza, citerò anche la sostituzione dei comandi e spiegherò perché non è consigliata:

cp $(grep -l "pattern" input) directory/

(La sintassi del backtick cp `grep -l "pattern" input` directory/ è più o meno equivalente, ma è obsoleto e ingombrante; non usarlo.)

Questo fallirà se l'output da grep produce un nome di file che contiene spazi bianchi o un metacarattere della shell.

Naturalmente, va bene usare questo se sai esattamente quale file nomina il grep possono produrre e hanno verificato che nessuno di essi è problematico. Ma per uno script di produzione, non usare questo.

Ad ogni modo, per lo scenario dell'OP, in cui è necessario fare riferimento a ciascuna corrispondenza individualmente e aggiungere un'estensione ad essa, il xargs o while read le alternative sono comunque superiori.

Nel caso peggiore (ovvero nomi di file problematici o non specificati), passa le corrispondenze a una subshell tramite xargs :

grep -l "pattern" input |
xargs -r sh -c 'for f; do cp "$f" "$f.bac"; done' _

... dove ovviamente lo script all'interno del for loop potrebbe essere arbitrariamente complesso.

Nel caso ideale, il comando che vuoi eseguire è abbastanza semplice (o versatile) da potergli semplicemente passare un elenco arbitrariamente lungo di nomi di file. Ad esempio, GNU cp ha un -t opzione per facilitare questo uso di xargs (il -t L'opzione consente di inserire la directory di destinazione prima sulla riga di comando, quindi puoi inserire tutti i file che vuoi alla fine del comando):

grep -l "pattern" input | xargs cp -t destdir

che si espanderà in

cp -t destdir file1 file2 file3 file4 ...

per un numero di corrispondenze pari a xargs può entrare nella riga di comando di cp , ripetuto tante volte quante sono necessarie per passare tutti i file a cp . (Sfortunatamente, questo non corrisponde allo scenario dell'OP; se devi rinominare ogni file durante la copia, devi passare solo due argomenti per cp invocazione:il nome del file di origine e il nome del file di destinazione in cui copiarlo.)

Quindi, in altre parole, se usi la sintassi di sostituzione dei comandi e grep produce un davvero lungo elenco di corrispondenze, rischi di imbatterti in ARG_MAX ed errori "Elenco argomenti troppo lungo"; ma xargs lo eviterà specificatamente copiando invece solo il numero di argomenti che può tranquillamente passare a cp alla volta ed eseguendo cp più volte se necessario invece.


Puoi usare xargs :

grep 'pattern' input | xargs -I% cp "%" "%.bac"

Puoi usare $() per interpolare l'output di un comando. Quindi, potresti usare kill -9 $(grep -hP '^\d+$' $(ls -lad /dir/*/pid | grep -P '/dir/\d+/pid' | awk '{ print $9 }')) se lo volessi.


Oltre alla buona risposta di Chris Jester-Young, direi che xargs è anche una buona soluzione per queste situazioni:

grep ... `ls -lad ... | awk '{ print $9 }'` | xargs kill -9

ce la farà. Tutti insieme:

grep -hP '^\d+$' `ls -lad /dir/*/pid | grep -P '/dir/\d+/pid' | awk '{ print $9 }'` | xargs kill -9

Linux
  1. Come usare il comando Linux grep

  2. Come assegnare l'output di un comando Linux a una variabile

  3. Come passare i parametri a un alias?

  4. Come eseguire il grep con l'output a colori

  5. Come aggiungere l'output a un file?

Come passare la password al comando SSH in Linux

Come usare grep in Linux

Come posso eseguire il loop sull'output di un comando di shell?

Come passare argomenti a uno script richiamato dal comando source?

Come passare più argomenti da eseguire con lo script .sh

Come passare l'output del comando come diversi argomenti a un altro comando