GNU/Linux >> Znalost Linux >  >> Linux

Jak předat výstup příkazu jako více argumentů jinému příkazu

Pro úplnost také zmíním substituci příkazů a vysvětlím, proč se to nedoporučuje:

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

(Syntaxe backtick cp `grep -l "pattern" input` directory/ je zhruba ekvivalentní, ale je zastaralý a nepraktický; nepoužívejte to.)

Toto selže, pokud je výstup z grep vytvoří název souboru, který obsahuje mezery nebo metaznak shellu.

Samozřejmě je dobré toto použít, pokud přesně víte, který soubor se jmenuje grep mohou produkovat a mají ověřeno, že žádný z nich není problematický. Ale pro produkční scénář toto nepoužívejte.

Každopádně pro scénář OP, kde je třeba odkazovat na každý zápas jednotlivě a přidat k němu rozšíření, xargs nebo while read alternativy jsou každopádně lepší.

V nejhorším případě (to znamená problematické nebo nespecifikované názvy souborů) předejte shody do subshell pomocí xargs :

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

... kde je zjevně skript uvnitř for smyčka může být libovolně složitá.

V ideálním případě je příkaz, který chcete spustit, natolik jednoduchý (nebo všestranný), že mu můžete jednoduše předat libovolně dlouhý seznam názvů souborů. Například GNU cp-t možnost usnadnit toto použití xargs (-t volba umožňuje umístit cílový adresář na první na příkazovém řádku, takže na konec příkazu můžete umístit libovolný počet souborů):

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

který se rozšíří do

cp -t destdir file1 file2 file3 file4 ...

pro tolik shod jako xargs se vejde do příkazového řádku cp , opakujte tolikrát, kolikrát je potřeba, aby byly všechny soubory předány cp . (Bohužel to neodpovídá scénáři OP; pokud potřebujete při kopírování přejmenovat každý soubor, musíte zadat pouze dva argumenty na cp vyvolání:název zdrojového souboru a název cílového souboru, do kterého se má kopírovat.)

Tedy jinými slovy, pokud použijete syntaxi substituce příkazu a grep vytváří skutečně dlouhý seznam shod, riskujete, že narazíte na ARG_MAX a chyby "Seznam argumentů je příliš dlouhý"; ale xargs konkrétně se tomu vyhne tím, že místo toho zkopíruje pouze tolik argumentů, kolik může bezpečně předat do cp najednou a běží cp v případě potřeby vícekrát.


Můžete použít xargs :

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

Můžete použít $() k interpolaci výstupu příkazu. Můžete tedy použít kill -9 $(grep -hP '^\d+$' $(ls -lad /dir/*/pid | grep -P '/dir/\d+/pid' | awk '{ print $9 }')) pokud byste chtěli.


Kromě dobré odpovědi Chrise Jestera-Younga bych řekl, že xargs je také dobrým řešením pro tyto situace:

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

udělá to. Všichni dohromady:

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

Linux
  1. Jak předat výstup jednoho příkazu jako argument druhému?

  2. Jak najít více řetězců v souborech?

  3. Jak zachytit výstup top příkazu do souboru v linuxu?

  1. Jak mohu zacyklit výstup příkazu shellu?

  2. Jak předat argumenty skriptu vyvolanému příkazem source?

  3. Jak předat více argumentů ke spuštění pomocí skriptu .sh

  1. Jak uložit výstup příkazu do souboru v Linuxu

  2. Jak grep ps výstup s hlavičkami

  3. Jak předat výstup příkazu jako několik argumentů jinému příkazu