web-dev-qa-db-ja.com

複数のコマンドを含むxargs

現在のディレクトリで、ファイル名と内容を印刷したいと思います。ファイル名や内容を別々に印刷できます

find . | grep "file_for_print" | xargs echo
find . | grep "file_for_print" | xargs cat

しかし、私が欲しいのは、次のようにそれらを一緒に印刷することです。

file1
line1 inside file1
line2 inside file1
file2
line1 inside file2
line2 inside file2

引数として複数のコマンドを含むxargs を読んで、試しました

find . | grep "file_for_print" | xargs -I % sh -c 'echo; cat;'

しかし、動作しません。私はxargsに精通していないので、「-I%sh-c」が正確に何を意味するのかわかりません。誰かが私を助けることができますか?ありがとうございました!

11
user987654

まず、次の間に実質的な違いはありません。

find . | grep "file_for_print" | xargs echo

そして

find . -name "file_for_print*"

ただし、2番目のファイル名はthis_is_not_the_file_for_printのようなファイル名と一致せず、ファイル名を1行に1つずつ出力します。また、grepがそのほとんどを破棄するためだけに、再帰的なディレクトリ構造全体を生成して印刷する必要がないため、はるかに高速になります。

find . -name "file_for_print*"

実際にはまったく同じです

find . -name "file_for_print*" -print

ここで、-printアクションは、一致した各ファイル名の後に改行を出力します。 findにアクションを指定しない場合は、-printが必要であると見なされます。しかし、それよりも多くのトリックがあります。例えば:

find . -name "file_for_print*" -exec cat {} \;

-execアクションにより、findは\;まで次のコマンドを実行し、{}を一致する各ファイル名に置き換えます。

findは、それ自体を単一のアクションに制限しません。あなたはそれをあなたが望む多くのことをするように言うことができます。そう:

find . -name "file_for_print*" -print -exec cat {} \;

おそらくあなたが望むものはかなりうまくいくでしょう。

この非常に便利なユーティリティの詳細については、次のように入力してください。

man find

または

info find

そしてそれについてすべて読んでください。

14
rici

find . | grep "file_for_print" | xargs -I % sh -c 'echo %; cat %;'(OPがありませんでした%s)

25
necromancer

まだ言われていないので:-I %はxargsに '%'をあなたが与えたコマンドの引数に置き換えるように指示します。 sh -c '...'は、新しいシェルでコマンド'...'を実行することを意味します。

そう

xargs -I % sh -c 'echo %; cat %;'

xargsに指定されたすべてのファイル名に対して、echo [filename]の後にcat [filename]が実行されます。 echoコマンドとcatコマンドは、別のシェルプロセス内で実行されますが、これは通常は問題ではありません。 xargsに渡されたコマンド内に%記号がないため、バージョンは機能しませんでした。


同じことを達成するために、このコマンドを使用する価値があります。

find -name "*file_for_print*" | parallel 'echo {}; cat {};'

単純だからです(parallelは自動的に{}を置換文字として使用し、デフォルトで複数のコマンドを受け取ることができます)。

10
dshepherd

この特定のケースでは、とにかく各コマンドは個々のファイルごとに実行されるため、xargsを使用する利点はありません。 'find'に-execを2回追加するだけです。

find . -name "*file_for_print*" -exec echo {} \; -exec cat {} \;

この場合、riciが指摘する最初のechoの代わりに-printを使用できますが、この例は、単一のfindで2つの任意のコマンドを実行する機能を示しています。

1
tavvit

独自のbash関数を作成するのはどうですか?

#!/bin/bash

myFunction() {
    while read -r file; do
        echo "$file"
        cat "$file"
    done
}

find . -name "file_for_print*" | myFunction