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


11

我设法通过重新格式化保存有价值数据的分区来拍摄自己的痛处(真的很糟)。当然,这不是故意的,但它确实发生了。

但是,我设法使用testdiskphotorec恢复了大多数数据。现在,我将所有数据分发到了近25,000个目录中。大多数文件是.txt文件,其余文件是图像文件。每个目录中有300多个.txt文件。

我可以grep或用来find从.txt文件中提取某些字符串,然后将它们输出到文件中。例如,这是我用来验证数据是否在恢复的文件中的一行:

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

我可以将“ searchPattern”输出到文件,但这只是给了我这种模式。这是我真正想要完成的工作:

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

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


因此,使用您提供的命令,它可以为您提供所需的结果,但您希望将输出重定向到文本文件?
ryekayo 2014年

阅读我的问题后,以“ Go through ...”开头的段落听起来像psuedocode。也许我可以用几行for / if Python代码来获得它的代码。当我等待一个更明智的答复时,将给您一个机会
Ami

它肯定是psuedocode,我确定您也可以找到一种在bash中执行此操作的方法。
ryekayo 2014年

@ryekayo,是的,它给了我输出,但这只是查找特定类型数据所在的文件,这告诉我该文件中还有更多数据。因此,我想获取该文件中的所有内容并将它们写入另一个文件。
2014年

您可能可以将该命令包装在某种if语句中,甚至可以包装一个可以调用函数的开关例,该函数可以根据if语句的大小写或结果来显示内容
ryekayo 2014年

Answers:


10

如果我正确理解您的目标,则可以执行以下操作:

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

这将查找中的所有*.txt文件./recup*/,对中的每个文件进行测试searchPattern,如果与之匹配则为cat文件。所有cated文件的输出将定向到中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


是的,我认为可以做到。这为我提供了工作基础。因为我要搜索多个字符串,所以我认为使用for / if代码和多个elif可以帮助我自动执行任务。谢谢
阿美(Ami)2014年

那甚至比我在想什么洛尔
ryekayo

那似乎没有用。收到此错误:“无法执行/ usr / bin / find:参数列表过长”
Ami

@Ami更新了答案以提供该问题的解决方案。
帕特里克

2
@Ami如果您正在使用多个字符串,它可能是简单的,只是一切积极的文件名保存到另一个文件(grep -l),然后|sort|uniqcat从文件列表。
Sparhawk

3

而不是输出模式,而是在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

2
我也喜欢Patrick的“ two -exec”选项,除了它会为每个文件引起一个新的fork(好,clone())和exec。通常,您可以使用\+而不是\;避免该问题,但是我不知道这对-exec args的工作方式(我怀疑是“很差”)。使用一对xargs,您将只产生几个新进程,这对于许多文件来说应该更快。
dannysauer 2014年

这看起来也不错。谢谢。一个小问题:最后xargs之后的猫应该输出到文件中,对吗?
2014年

当我第一次阅读它时,我不认为该问题指定了文件内容应存放的位置。所有这三个命令把文件(S)含量在标准输出上,所以你只是追加(到最后)>afile|acommand或什么是适合您的情况。:)
dannysauer 2014年

好答案,我需要猫pg_hba.conf sudo find /* -name pg_hba.conf | xargs sudo cat
应用工作

这有点题外话,但我更喜欢使用sudo xargs代替xargs sudo。运行时xargs sudo,它会假设命令为,构建命令行sudo cat args。但是cat在/ bin中,因此sudo运行/bin/cat args。如果您的命令位于更长的目录中,例如/ usr / local / bin,那么sudo实际运行的命令可能会导致命令行太长,并且导致难以跟踪的错误。最重要的是,sudo xargs仅记录您运行xargs的时间,同时xargs sudo记录带有所有参数的命令-导致一些冗长的sudo日志行。:)
dannysauer

1

这不是最佳代码,但非常简单,如果效率不成问题,它将很好地工作。问题在于,即使在文件中已经找到字符串,它也会多次遍历文件。

首先,搜索您的字符串并将匹配的文件写入列表。

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

重复此步骤searchPattern,必要时进行更换。这会在产生匹配文件的列表/tmp/file_list

问题在于此文件中可能有重复项。因此,我们可以将重复项替换为|sort|uniq。该sort零件将重复项彼此相邻放置,以便uniq可以将其删除。然后,您可以将cat这些文件一起使用xargs(每个文件名用newline分隔\n)。因此,

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

与其他答案不同,它有两个步骤以及一个临时文件,因此,如果您要查找多个模式,则我真的建议您这样做。


0

根据您的外壳和环境,您可以这样做(以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)

“完成”之后的功能是什么?我真正想要的是修改if块,以便将包含匹配模式的文件写入其他文件。
2014年

它仅列出找到的“ .txt”文件,每个文件都以空字符终止(这样对于包含空格和其他字符的文件名是安全的)。该while环路,则读取列表并执行grep/有条件cat的部分。
steeldriver

当我尝试运行代码时,出现以下错误:./recoverData.sh:语法错误:“(”意外。这是来自find命令周围的括号
Ami

您正在使用什么外壳?该过程替换语法特定于
bash-

1
您可以直接在交互式bash shell中执行命令,也可以将命令放入第一行包含shebang的文件中#!/bin/bash,使其可以执行chmod +x recoverData.sh,然后使用来执行./recoverData.sh。千万不能使用sh recoverData.sh,因为/bin/sh可能是一个dash
steeldriver
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.