ファイル内の数百の文字列に対してディレクトリ内の数千のファイルをgrepする方法


11

私はgrep声明を作成しようとしています、そしてそれは私を殺しています。arguments list too longエラーが出てもううんざりです。ファイルがありますsubset.txt。それを呼び出しましょう。これには、などの特定の文字列を含む数百行が含まれていMO43312948ます。私のオブジェクトディレクトリには何千ものファイルがあり、に記載されsubset.txtている文字列を含むすべてのファイルを別のディレクトリにコピーする必要があります。

私はこれから始めて、一致するファイルをオブジェクトディレクトリから返すだけにしました。

grep -F "$(subset.txt)" /objects/*

「bash:/ bin / grep:引数リストが長すぎる」というメッセージが表示され続ける


6
なぜあなた"$(subset.txt)"はそのようなコマンドを入れたのですか?これはコマンド置換であり、シェル subset.txt(コマンドまたはスクリプトであるかのように)実行します。
JigglyNaga 16

回答:


23

あなたはへのターゲットとしてディレクトリを渡すことができますgrep-Rしてと入力パターンのファイル-f

  -f FILE, --file=FILE
          Obtain patterns from FILE, one per line.  If this option is used
          multiple  times  or  is  combined with the -e (--regexp) option,
          search for all patterns given.  The  empty  file  contains  zero
          patterns, and therefore matches nothing.

   -R, --dereference-recursive
          Read all files under each directory,  recursively.   Follow  all
          symbolic links, unlike -r.

だから、あなたは探しています:

grep -Ff subset.txt -r objects/

一致するファイルのリストは次のようにして取得できます。

grep -Flf subset.txt -r objects/

したがって、最終的なリストが長すぎない場合は、次のようにすることができます。

 mv $(grep -Flf subset.txt -r objects/) new_dir/

それがargument list too longエラーを返す場合は、以下を使用します。

grep -Flf subset.txt -r objects/ | xargs -I{} mv {} bar/

また、ファイル名にスペースやその他の奇妙な文字が含まれている可能性がある場合は、(GNUを想定してgrep)使用します。

grep -FZlf subset.txt -r objects/ | xargs -0I{} mv {} bar/

最後に、バイナリファイルを除外する場合は、次を使用します。

grep -IFZlf subset.txt -r objects/ | xargs -0I{} mv {} bar/

…またはmv、1つの引数で数千の呼び出しが発生する可能性を回避... | xargs -0 mv -t bar/します(オプションがmvサポートされている-t場合)。
David Foerster、2016

11

使用する

grep -F -f subset.txt 

subset.txtファイルから読み取るようにgrepに指示します。

findを使用してファイルをウォークできます。

find . -type f -exec grep -F -f subset.txt {} \;

または

find . -type f -exec grep -F -f subset.txt {}  +

使用して任意の利点findの代わりに、-rあなたは追加のフィルタリングを行うこと以外に?
phk

1
@phk grep -rは、通常のファイルへのシンボリックリンクを検索します。これは、望ましい場合と望ましくない場合があります(同じツリー内を指している場合は、同じファイルを2回検索します。外部を指している場合は、ファイルを検索します。望まれる)。
Gilles「SO-邪悪なことをやめなさい」

の最新バージョンにgrepは、シンボリックリンクとの相互作用を制御するオプションがあります(man grep現在のシステムの詳細を決定するため)。再帰grepは、を介してすべてのファイルを個別に実行するよりもはるかに高速grepですfind
ペリー

1
@ペリー、あなたはそれについて確信していますか?どうして?また、この回答はを使用-exec +しているため、ファイルをグループ化し、ファイルごとに1つのgrepを実行しないことに注意してください 。
terdon

私は修正された状態で、-exec {} +vs の異なるセマンティクスに気付いていませんでした-exec {} \;...あなたは毎日何か新しいことを学びます(プロセスの作成とパターン解析のオーバーヘッドにより、単一の再帰grepが複数grepのの実行よりも速くならない理由はまだわかりませんfindが、私はそれをバックアップするために渡す特定の番号はありません)。
ペリー

3

grepをさらに高速化したい場合は、実行する前にシェルでロケールを設定できます。つまり、「LC_ALL = c」を使用します。これはgrepに継承され、不要な場合はUnicode処理を無効にし、場合によってはgrepを大幅に高速化できます。これを文書化した素晴らしいブログがhttp://www.inmotionhosting.com/support/website/ssh/speed-up-grep-searches-with-lc-allにあります。このトリックは、grepだけでなく、bashシェルスクリプトも高速化できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.