findを使用して見つかったファイルの内容を単一のファイルにマージするにはどうすればよいですか?

findを使用して見つかったファイルの内容を単一のファイルにマージするにはどうすればよいですか?

私は貴重なデータを含むパーティションを再フォーマットして、病気の場所(非常にひどく)を自分で撮影することができました。もちろん意図したものではありませんでしたが、そのようなことが起こりました。

しかし、ほとんどのデータを使用しtestdiskて回復しました。photorecこれで、すべてのデータがほぼ25,000のディレクトリに分散されています。ほとんどのファイルは.txtファイルで、残りは画像ファイルです。各ディレクトリには300以上の.txtファイルがあります。

grep.txtファイルから特定の文字列を抽出し、.txtを使用してfindファイルに出力できます。たとえば、次の行を使用して、データが回復されたファイルにあることを確認します。

find ./recup*/ -name '*.txt' -print | xargs grep -i "searchPattern"

「searchPattern」をファイルに出力できますが、これはパターンのみを提供するだけです。これが私が本当に達成したいものです:

すべてのファイルに移動し、特定の文字列を探します。ファイルで文字列が見つかった場合は、ファイルの内容全体を出力ファイルに変換します。パターンが複数のファイルで見つかると、後続のファイルの内容がこの出力ファイルに追加されます。私が探しているパターンを出力するのではなく、パターンが見つかったファイルの内容全体を出力したいことに注意してください。

私はこれが可能だと思いますが、ファイル内の特定のパターンを特定した後、ファイルのすべての内容を取得する方法がわかりません。

答え1

あなたの目標を正しく理解すれば、次のようなものを得ることができます。

find ./recup*/ -name '*.txt' -exec grep -qi "searchPattern" {} \; -exec cat {} \; > outputfile.txt

*.txtその後、すべてのファイルを探し./recup*/、各ファイルをテストしsearchPattern、一致する場合はそのcatファイルを探します。すべてのedファイルの出力catoutputfile.txt

各パターンと出力ファイルに対してこれを繰り返します。


一致するディレクトリが多い場合は、./recup*1つのディレクトリで終わることができますargument list too long error。この問題を解決する簡単な方法は、次のことです。

find ./ -mindepth 2 -path './recup*.txt' -exec grep -qi "searchPattern" {} \; -exec cat {} \; > outputfile.txt

これはフルパスと一致します。だから./recup01234/foo/bar.txt一致します。したがって-mindepth 2、一致しません./recup.txt。または./recup0.txt

答え2

パターンを出力する代わりに、grepで「-l」を使用してファイル名を出力し、catへの入力として使用できます。

find ./recup*/ -name '*.txt' -print | xargs grep -li "searchPattern" | xargs cat

または

cat $( find ./recup*/ -name '*.txt' -print | xargs grep -li "searchPattern")

残りの詳細はあなたが書くことができるようです。ちなみに、ファイル名にスペースやその他の奇妙な文字がある可能性がある場合(この特別なケースではありませんが、将来の目的のために)findで-print0を使用し、grepで-Zを使用し、xargsで-0オプションと組み合わせてnull を使用します。改行の代わりにファイル名の間にバイトを追加します。

find ./recup*/ -name '*.txt' -print0 | xargs -0 grep -Zli "searchPattern" | xargs -0 cat

答え3

これはまさに最適なコードではありませんが、非常に簡単で効率が問題にならない場合はうまく機能します。問題は、文字列がファイル内ですでに見つかった場合でも、ファイルを複数回grepすることです。

まず、文字列を検索し、一致するファイルをリストに作成します。

find ./recup*/ -name '*.txt' -execdir grep -il "searchPattern" {} >> /tmp/file_list \;

searchPattern必要に応じて交換するには、この手順を繰り返します。これにより、一致するファイルのリストが生成されます/tmp/file_list

問題は、ファイルに重複がある可能性があることです。したがって、重複項目を|sort|uniq。このコンポーネントは、重複したアイテムを削除するsortために互いに隣り合って配置されます。その後、これらのファイルを一緒に使用uniqできます(各ファイル名は改行文字で区切られています)。したがって、catxargs\n

</tmp/file_list sort | uniq | xargs -d "\n" cat > final_file.txt

他の回答とは異なり、ここには2つのステップと一時ファイルがあるため、検索するパターンが複数ある場合にのみお勧めします。

答え4

シェルと環境に応じてこれを行うことができます(bashから)。

while IFS= read -r -d '' file; do
  if grep -qim1 'searchPattern1\|searchPattern2\|searchPattern3' "$file"; then
    cat "$file" >> some/other/file
  fi
done < <(find ./recup*/ -name '*.txt' -print0)

パターンに基づいて結果を分離するには、次のように変更できます。

while IFS= read -r -d '' file; do
  if grep -qim1 'searchPattern1' "$file"; then
    cat "$file" >> some/other/file1
  elif grep -qim1 'searchPattern2' "$file"; then
    cat "$file" >> some/other/file2
  elif grep -qim1 'searchPattern3' "$file"; then
    cat "$file" >> some/other/file3
  fi
done < <(find ./recup*/ -name '*.txt' -print0)

関連情報