find
を実行してからファイルのリストを取得しています。どのようにしてcat
のような別のユーティリティにパイプし(catがこれらすべてのファイルの内容を表示するように)、基本的にこれらのファイルから何かをgrep
する必要があります。
別のプロセスへのパイピング(これは、あなたがやろうとしていると言ったことを達成することはできませんが):
command1 | command2
これにより、command1の出力がcommand2の入力として送信されます。
find
上の-exec
(これはあなたがしたいことをしますが、find
に固有です)
find . -name '*.foo' -exec cat {} \;
(find
と-exec
の間はすべて、すでに使用していた検索述語です。{}
は、見つかった特定のファイルをコマンドに置き換えます(この場合はcat {}
)。 \;
は-exec
コマンドを終了します。)
あるプロセスの出力をコマンドライン引数として別のプロセスに送信する
command2 `command1`
例えば:
cat `find . -name '*.foo' -print`
(これらはBACK-QUOTESであり、通常の引用符ではありません(キーボードのチルダ〜の下)。)これにより、command1
の出力がコマンドライン引数としてcommand2
に送信されます。ただし、スペース(改行など)を含むファイル名は個別の引数に分割されることに注意してください。
POSIX 2008では、 find
に+
マーカーが追加されました。これは、xargs
と非常によく似た、合理的な数のファイルを自動的にグループ化することを意味します。
ファイル名の問題は-0
オプションのないxargs
の問題であり、 'ゼロのファイル名でも実行する'問題は-0
オプションの有無にかかわらず問題です - しかしGNU xargs
には-r
または--no-run-if-empty
オプションがありますそれを防ぐために。また、この表記はプロセス数を削減します。パフォーマンスの違いを測定する可能性が高いというわけではありません。したがって、あなたは賢明に書くことができます:
find . -exec grep something {} +
find . -print | xargs grep something
Linuxを使用している場合、またはGNU find
およびxargs
コマンドを使用している場合は、find
とともに-print0
およびxargs
とともに-0
を使用して、スペースやその他の奇妙なボールを含むファイル名を処理します。
find . -print0 | xargs -0 grep something
grep
の結果を調整するファイル名(テキストのみ)が不要な場合は、grep
に適切なオプションを追加します(通常、「見出し」を抑制するには-h
)。ファイル名がgrep
で確実に表示されるようにするには(1つのファイルしか見つからない場合、またはgrep
の最後の呼び出しで1つのファイル名しか指定されない場合でも)、xargs
コマンド行に/dev/null
を追加します。 2つのファイル名.
find
コマンドによって返されたファイルのリストをcat
コマンドに渡す方法はいくつかありますが、技術的にはすべてがパイピングを使用するわけではなく、実際にcat
に直接パイピングするものはありません。
最も簡単なのは、バックティック(`
)を使用することです:
cat `find [whatever]`
これはfind
の出力を取得し、それをcat
のコマンドラインに効果的に配置します。 find
の出力が多すぎる(コマンドラインに収まらない)場合、または出力に特殊文字(スペースなど)がある場合、これはうまく機能しません。
bash
を含む一部のシェルでは、バックティックの代わりに$()
を使用できます。
cat $(find [whatever])
これは移植性は劣りますが、ネスト可能です。それ以外は、バックティックとほぼ同じ注意事項があります。
見つかったものに対して他のコマンドを実行することはfind
の一般的な使用であるため、findには、見つかった各ファイルに対してコマンドを実行する-exec
アクションがあります。
find [whatever] -exec cat {} \;
{}
はファイル名のプレースホルダーであり、\;
はコマンドの終わりを示します(-exec
の後に他のアクションを含めることができます)。
これは、複数のファイル名を渡すcat
の単一インスタンスを実行するのではなく、ファイルごとにcat
を1回実行します。複数のファイル名は非効率的であり、一部のコマンドに必要な動作を持たない場合があります(cat
には問題ありません)構文も入力するのが面倒です-セミコロンはシェルにとって特別なので、セミコロンをエスケープする必要があります!
find
の一部のバージョン(特にGNUバージョン)では、;
を+
に置き換えて、-exec
の追加モードを使用して、cat
のインスタンスをより少なく実行できます。
find [whatever] -exec cat {} +
これにより、cat
の各呼び出しに複数のファイル名が渡され、より効率的になります。
ただし、これはnotであるため、単一の呼び出しを使用することが保証されています。コマンドラインが長すぎる場合、引数はcat
の複数の呼び出しに分散されます。 cat
の場合、これはおそらく大した問題ではありませんが、他の一部のコマンドでは、これにより動作が望ましくない方法で変更される場合があります。 Linuxシステムでは、コマンドラインの長さの制限が非常に大きいため、複数の呼び出しに分割することは、他のOSに比べて非常にまれです。
クラシック/ポータブルアプローチは、xargs
を使用することです。
find [whatever] | xargs cat
xargs
は、指定されたコマンド(この場合はcat
)を実行し、stdinから読み取った内容に基づいて引数を追加します。 -exec
と+
のように、これは必要に応じてコマンドラインを分割します。つまり、find
の出力が多すぎる場合、cat
が複数回実行されます。前の-exec
に関するセクションで述べたように、この分割が異なる動作を引き起こす可能性のあるコマンドがいくつかあります。 xargs
は区切り文字として空白のみを使用するため、このようにxargs
を使用すると、ファイル名のスペースに問題があることに注意してください。
最も堅牢で、移植性があり、効率的な方法でもxargs
が使用されます。
find [whatever] -print0 | xargs -0 cat
-print0
フラグは、ファイル名の間に\0
(ヌル文字)区切り文字を使用するようfind
に指示し、-0
フラグは、これらの\0
区切り文字を期待するようにxargs
に指示します。これは-exec
...+
アプローチとほとんど同じ動作をしますが、より移植性があります(ただし、残念ながら詳細です)。
これを達成するには(bashを使用して)、次のようにします。
cat $(find . -name '*.foo')
これは「コマンド置換」として知られていて、デフォルトで改行を取り除きます。
より多くの情報 ここ
シェルスクリプトの仕事のように思えます。
for file in 'find -name *.xml'
do
grep 'hello' file
done
またはそのようなもの
これは私が興味を持っている内容を含むファイル名を見つけるための私の方法です。
find . -name \*.xml | while read i; do grep '<?xml' "$i" >/dev/null; [ $? == 0 ] && echo $i; done
私はこのようなものを使います:
find . -name <filename> -print0 | xargs -0 cat | grep <Word2search4>
"find"の "-print0
"引数と "xargs"の "-0
"引数は、ファイルパス/名前の空白を正しく処理するために必要です。
Findコマンドには-exec引数があり、これをこのようなことに使うことができます。それを直接使ってgrepを実行することもできます。
例えば( ここから、このページの他の良い例 ):
find . -exec grep "www.athabasca" '{}' \; -print
Bashでは、以下が適切でしょう。
find /dir -type f -print0 | xargs -0i cat {} | grep whatever
これは/dir
ディレクトリ内のすべてのファイルを見つけ、安全にxargs
name__を駆動するgrep
name__にファイル名をパイプで送ります。
/dir
に何千ものファイルがある場合は、xargs
name__をスキップするのはお勧めできません。引数リストの長さが長すぎるとcat
name__が壊れます。 xargs
name__はそれらすべてをあなたのために整理します。
find
name__への-print0
引数は、スペースを含むファイル名を正しく処理するために、xargs
name__への-0
引数と噛み合っています。 xargs
name__への-i
引数を使用すると、必要に応じてcat
name__コマンドラインのファイル名を挿入できます。大括弧は、cat
name__からfind
name__コマンドにパイプされたファイル名に置き換えられます。
これが私の一般的な使用のためのショットです:
grep YOURSTRING `find .`
ファイル名を表示します
これは私のために働く
find _CACHE_* | while read line; do
cat "$line" | grep "something"
done
これはファイルの名前と内容を再帰的にのみ表示します。
find . -type f -printf '\n\n%p:\n' -exec cat {} \;