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 má -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