如何将使用 find 找到的文件内容合并到单个文件中?

如何将使用 find 找到的文件内容合并到单个文件中?

通过重新格式化保存有价值数据的分区,我设法向自己的痛处(非常糟糕)开枪。当然这不是故意的,但是却发生了。

然而,我设法使用testdiskphotorec恢复了大部分数据。现在我已经将所有数据分布在近 25,000 个目录中。大多数文件是.txt 文件,其余的是图像文件。每个目录中有超过300个.txt文件。

我可以grep或使用find从 .txt 文件中提取某些字符串并将其输出到文件中。例如,我用下面的一行来验证我的数据是否位于恢复的文件中:

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

我可以将“searchPattern”输出到文件中,但这只是给了我该模式。这就是我真正想要实现的目标:

浏览所有文件并查找特定字符串。如果在文件中找到该字符串,则将该文件的所有内容 cat 到输出文件。如果在多个文件中找到该模式,则将后续文件的内容附加到该输出文件。请注意,我只是不想输出我正在搜索的模式,而是输出找到模式的文件的所有内容。

我认为这是可行的,但我只是不知道如何在从中 grep 特定模式后获取文件的所有内容。

答案1

如果我正确理解你的目标,以下将实现你想要的:

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

这将查找*.txt中的所有文件./recup*/,测试每个文件searchPattern,如果匹配,则该cat文件。所有 ed 文件的输出cat将定向到outputfile.txt.

对每个模式和输出文件重复此操作。


如果您有大量匹配的目录./recup*,您可能最终会得到一个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 选项来使用文件名之间的空字节而不是换行符。

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可以将它们删除。然后您可以将cat这些文件一起使用xargs(每个文件名用换行符分隔\n)。因此,

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

与其他答案不同,这有两个步骤和一个临时文件,所以我真的只在您有多个模式需要查找时才推荐它。

答案4

根据你的 shell 和环境,你可以这样(在 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)

相关内容