web-dev-qa-db-ja.com

findコマンドによって返されたファイルのリストをcatにパイプしてすべてのファイルを表示する方法

findを実行してからファイルのリストを取得しています。どのようにしてcatのような別のユーティリティにパイプし(catがこれらすべてのファイルの内容を表示するように)、基本的にこれらのファイルから何かをgrepする必要があります。

184
Devang Kamdar
  1. 別のプロセスへのパイピング(これは、あなたがやろうとしていると言ったことを達成することはできませんが):

    command1 | command2
    

    これにより、command1の出力がcommand2の入力として送信されます。

  2. find上の-exec(これはあなたがしたいことをしますが、findに固有です)

    find . -name '*.foo' -exec cat {} \;
    

    find-execの間はすべて、すでに使用していた検索述語です。{}は、見つかった特定のファイルをコマンドに置き換えます(この場合はcat {})。 \;-execコマンドを終了します。)

  3. あるプロセスの出力をコマンドライン引数として別のプロセスに送信する

    command2 `command1`
    

    例えば:

    cat `find . -name '*.foo' -print`
    

    (これらはBACK-QUOTESであり、通常の引用符ではありません(キーボードのチルダ〜の下)。)これにより、command1の出力がコマンドライン引数としてcommand2に送信されます。ただし、スペース(改行など)を含むファイル名は個別の引数に分割されることに注意してください。

306
kenj0418

現代版

POSIX 2008では、 find+マーカーが追加されました。これは、xargsと非常によく似た、合理的な数のファイルを自動的にグループ化することを意味します。

  1. あなたはファイル名の中の奇妙な文字について心配する必要はありません。
  2. コマンドがゼロのファイル名で呼び出されるのを心配する必要はありません。

ファイル名の問題は-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つのファイル名.

78

findコマンドによって返されたファイルのリストをcatコマンドに渡す方法はいくつかありますが、技術的にはすべてがパイピングを使用するわけではなく、実際にcatに直接パイピングするものはありません。

  1. 最も簡単なのは、バックティック(`)を使用することです:

    cat `find [whatever]`
    

    これはfindの出力を取得し、それをcatのコマンドラインに効果的に配置します。 findの出力が多すぎる(コマンドラインに収まらない)場合、または出力に特殊文字(スペースなど)がある場合、これはうまく機能しません。

  2. bashを含む一部のシェルでは、バックティックの代わりに$()を使用できます。

    cat $(find [whatever])
    

    これは移植性は劣りますが、ネスト可能です。それ以外は、バックティックとほぼ同じ注意事項があります。

  3. 見つかったものに対して他のコマンドを実行することはfindの一般的な使用であるため、findには、見つかった各ファイルに対してコマンドを実行する-execアクションがあります。

    find [whatever] -exec cat {} \;
    

    {}はファイル名のプレースホルダーであり、\;はコマンドの終わりを示します(-execの後に他のアクションを含めることができます)。

    これは、複数のファイル名を渡すcatの単一インスタンスを実行するのではなく、ファイルごとにcatを1回実行します。複数のファイル名は非効率的であり、一部のコマンドに必要な動作を持たない場合があります(catには問題ありません)構文も入力するのが面倒です-セミコロンはシェルにとって特別なので、セミコロンをエスケープする必要があります!

  4. findの一部のバージョン(特にGNUバージョン)では、;+に置き換えて、-execの追加モードを使用して、catのインスタンスをより少なく実行できます。

    find [whatever] -exec cat {} +
    

    これにより、catの各呼び出しに複数のファイル名が渡され、より効率的になります。

    ただし、これはnotであるため、単一の呼び出しを使用することが保証されています。コマンドラインが長すぎる場合、引数はcatの複数の呼び出しに分散されます。 catの場合、これはおそらく大した問題ではありませんが、他の一部のコマンドでは、これにより動作が望ましくない方法で変更される場合があります。 Linuxシステムでは、コマンドラインの長さの制限が非常に大きいため、複数の呼び出しに分割することは、他のOSに比べて非常にまれです。

  5. クラシック/ポータブルアプローチは、xargsを使用することです。

    find [whatever] | xargs cat
    

    xargsは、指定されたコマンド(この場合はcat)を実行し、stdinから読み取った内容に基づいて引数を追加します。 -exec+のように、これは必要に応じてコマンドラインを分割します。つまり、findの出力が多すぎる場合、catが複数回実行されます。前の-execに関するセクションで述べたように、この分割が異なる動作を引き起こす可能性のあるコマンドがいくつかあります。 xargsは区切り文字として空白のみを使用するため、このようにxargsを使用すると、ファイル名のスペースに問題があることに注意してください。

  6. 最も堅牢で、移植性があり、効率的な方法でもxargsが使用されます。

    find [whatever] -print0 | xargs -0 cat
    

    -print0フラグは、ファイル名の間に\0(ヌル文字)区切り文字を使用するようfindに指示し、-0フラグは、これらの\0区切り文字を期待するようにxargsに指示します。これは-exec...+アプローチとほとんど同じ動作をしますが、より移植性があります(ただし、残念ながら詳細です)。

34

これを達成するには(bashを使用して)、次のようにします。

cat $(find . -name '*.foo')

これは「コマンド置換」として知られていて、デフォルトで改行を取り除きます。

より多くの情報 ここ

9
Stphane

シェルスクリプトの仕事のように思えます。

for file in 'find -name *.xml'
do
   grep 'hello' file
done

またはそのようなもの

6
Gandalf

これは私が興味を持っている内容を含むファイル名を見つけるための私の方法です。

find . -name \*.xml | while read i; do grep '<?xml' "$i" >/dev/null; [ $? == 0 ] && echo $i; done
4
Greg

私はこのようなものを使います:

find . -name <filename> -print0 | xargs -0 cat | grep <Word2search4>

"find"の "-print0"引数と "xargs"の "-0"引数は、ファイルパス/名前の空白を正しく処理するために必要です。

3
ekinak

Findコマンドには-exec引数があり、これをこのようなことに使うことができます。それを直接使ってgrepを実行することもできます。

例えば( ここから、このページの他の良い例 ):

find . -exec grep "www.athabasca" '{}' \; -print 
2
Chad Birch

Bashでは、以下が適切でしょう。

find /dir -type f -print0 | xargs -0i cat {} | grep whatever

これは/dirディレクトリ内のすべてのファイルを見つけ、安全にxargsname__を駆動するgrepname__にファイル名をパイプで送ります。

/dirに何千ものファイルがある場合は、xargsname__をスキップするのはお勧めできません。引数リストの長さが長すぎるとcatname__が壊れます。 xargsname__はそれらすべてをあなたのために整理します。

findname__への-print0引数は、スペースを含むファイル名を正しく処理するために、xargsname__への-0引数と噛み合っています。 xargsname__への-i引数を使用すると、必要に応じてcatname__コマンドラインのファイル名を挿入できます。大括弧は、catname__からfindname__コマンドにパイプされたファイル名に置き換えられます。

2
McClain Looney

これが私の一般的な使用のためのショットです:

grep YOURSTRING `find .`

ファイル名を表示します

2
zakki

これは私のために働く

find _CACHE_* | while read line; do
    cat "$line" | grep "something"
done
0
Steven Penny

これはファイルの名前と内容を再帰的にのみ表示します。

find . -type f -printf '\n\n%p:\n' -exec cat {} \;
0

ggrep を使用してください。

ggrep -H -R -I "mysearchstring" *

現在のディレクトリまたはサブディレクトリにあるテキストを含むファイルをunixで検索します。

0
Underverse