如何为目录中的数百个字符串grep grep目录中的数千个文件


11

我试图写一条grep声明,这使我丧命。我也对收到arguments list too long错误感到厌倦。我有一个文件,我们称之为subset.txt。它包含数百行带有特定字符串的行,例如MO43312948。在我的对象目录中,我有成千上万个文件,我需要将包含列出的字符串的所有文件复制subset.txt到另一个目录中。

我试图以此开始只是从对象目录返回匹配的文件。

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

我不断收到`bash:/ bin / grep:参数列表太长``


6
为什么要这样"$(subset.txt)"输入命令?那就是命令替换,它将使您的shell 执行 subset.txt(就像它是命令或脚本一样)。
JigglyNaga

Answers:


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调用,每个调用都有一个参数:(... | xargs -0 mv -t bar/假设您mv支持该-t选项)。
David Foerster

11

grep -F -f subset.txt 

告诉grep从subset.txt文件读取。

您可以使用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在符号链接中搜索常规文件,这可能不理想(如果它们指向同一棵树,则表示您正在搜索同一文件两次;如果它们指向外部,则表示搜索的文件可能与否)是理想的)。
吉尔(Gilles)“所以,别再邪恶了”

现代版本的grep可以选择控制它们与符号链接的交互(man grep以确定当前系统的详细信息)。递归grep将是一个很多比运行速度更快grep的通过每一个单独的文件find
佩里

1
@Perry你确定吗?为什么?另外,请注意,此答案正在使用 -exec +,因此它将对文件进行分组,而不是每个文件运行一个grep。
terdon

我的立场是正确的,我没有意识到-exec {} +vs 的不同语义-exec {} \;……您每天都会学到一些新东西(由于过程创建和模式解析开销,我仍然没有理由为什么单个递归grep不会比grep运行多个s 快,find但是我没有具体的数字可以支持)。
佩里

3

如果要进一步提高grep的速度,可以在运行它之前在shell中设置语言环境,即使用“ LC_ALL = c”。这将被继承到grep中,并在不必要时禁用Unicode处理,并且在某些情况下可以极大地加快grep的速度。可以在http://www.inmotionhosting.com/support/website/ssh/speed-up-grep-searches-with-lc-all中找到有关此问题的出色博客。这个技巧还可以加快bash shell脚本的速度,而不仅仅是grep。

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.