Linux Unix命令列出包含字符串但*不*包含另一个字符串的文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4989519/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 02:50:58  来源:igfitidea点击:

Unix Command to List files containing string but *NOT* containing another string

linuxcommand-linefindcommandgrep

提问by Matrym

How do I recursively view a list of files that has one string and specifically doesn't have another string? Also, I mean to evaluate the text of the files, not the filenames.

如何递归查看具有一个字符串且特别没有另一个字符串的文件列表?另外,我的意思是评估文件的文本,而不是文件名。



Conclusion:

结论:

As per comments, I ended up using:

根据评论,我最终使用了:

find . -name "*.html" -exec grep -lR 'base\-maps' {} \; | xargs grep -L 'base\-maps\-bot'

This returned files with "base-maps" and not "base-maps-bot". Thank you!!

这返回了带有“base-maps”而不是“base-maps-bot”的文件。谢谢!!

采纳答案by Sander Marechal

Try this:

尝试这个:

grep -rl <string-to-match> | xargs grep -L <string-not-to-match>

Explanation: grep -lrmakes grep recursively (r) output a list (l) of all files that contain <string-to-match>. xargs loops over these files, calling grep -Lon each one of them. grep -Lwill only output the filename when the file does not contain <string-not-to-match>.

解释:grep -lr使 grep 递归 (r) 输出包含<string-to-match>. xargs 循环遍历这些文件,调用grep -L它们中的每一个。grep -L仅当文件不包含<string-not-to-match>.

回答by Chris

These answers seem off as the match BOTHstrings. The following command should work better:

这些答案似乎与BOTH字符串相匹配。以下命令应该工作得更好:

grep -l <string-to-match> * | xargs grep -c <string-not-to-match> | grep '\:0'

回答by kirelagin

Here is a more generic construction:

这是一个更通用的构造:

find . -name <nameFilter> -print0 | xargs -0 grep -Z -l <patternYes> | xargs -0 grep -L <patternNo>

This command outputs files whose name matches <nameFilter>(adjust findpredicates as you need) which contain <patternYes>, but do not contain <patternNo>.

此命令输出名称匹配<nameFilter>find根据需要调整谓词)的文件,其中包含<patternYes>,但不包含<patternNo>.

The enhancements are:

增强功能是:

  • It works with filenames containing whitespace.
  • It lets you filter files by name.
  • 它适用于包含空格的文件名。
  • 它允许您按名称过滤文件。

If you don't need to filter by name (one often wants to consider all the files in current directory), you can strip findand add -Rto the first grep:

如果您不需要按名称过滤(通常需要考虑当前目录中的所有文件),您可以删除find并添加-R到第一个grep

grep -R -Z -l <patternYes> | xargs -0 grep -L <patternNo>

回答by Tom

The use of xargs in the answers above is not necessary; you can achieve the same thing like this:

没有必要在上述答案中使用 xargs;你可以像这样实现同样的事情:

find . -type f -exec grep -q <string-to-match> {} \; -not -exec grep -q <string-not-to-match> {} \; -print

grep -qmeans run quietly but return an exit code indicating whether a match was found; findcan then use that exit code to determine whether to keep executing the rest of its options. If -exec grep -q <string-to-match> {} \;returns 0, then it will go on to execute -not -exec grep -q <string-not-to-match>{} \;. If that also returns 0, it will go on to execute -print, which prints the name of the file.

grep -q意味着安静地运行,但返回一个退出代码,指示是否找到匹配项;find然后可以使用该退出代码来确定是否继续执行其其余选项。如果-exec grep -q <string-to-match> {} \;返回 0,那么它将继续执行-not -exec grep -q <string-not-to-match>{} \;。如果它也返回 0,它将继续执行-print,打印文件名。

As another answer has noted, using findin this way has major advantages over grep -Rlwhere you only want to search files of a certain type. If, on the other hand, you really want to search all files, grep -Rlis probably quicker, as it uses one grepprocess to perform the first filter for all files, instead of a separate grepprocess for each file.

正如另一个答案所指出的那样,findgrep -Rl您只想搜索某种类型的文件相比,以这种方式使用具有主要优势。另一方面,如果您真的想搜索所有文件,grep -Rl可能会更快,因为它使用一个grep进程为所有文件执行第一个过滤器,而不是grep为每个文件执行单独的进程。

回答by Jahidfazal Patil

find . -maxdepth 1 -name "*.py" -exec grep -L "string-not-to-match" {} \;

找 。-maxdepth 1 -name "*.py" -exec grep -L "string-not-to-match" {} \;

This Command will get all ".py" files that don't contain "string-not-to-match" at same directory.

此命令将在同一目录中获取所有不包含“string-not-to-match”的“.py”文件。

回答by Ernst van Dijk

To match string A and exclude strings B & C being present in the same line I use, and quotes to allow search string to contain a space

匹配字符串 A 并排除出现在我使用的同一行中的字符串 B 和 C,并使用引号以允许搜索字符串包含空格

grep -r <string A> | grep -v -e <string B> -e "<string C>" | awk -F ':' '{print }'

Explanation: grep -r recursively filters all lines matching in output format

说明:grep -r 递归过滤输出格式中匹配的所有行

filename: line

文件名:行

To exclude (grep -v) from those lines the ones that also contain either -e string B or -e string C. awk is used to print only the first field (the filename) using the colon as fieldseparator -F

要从这些行中排除 (grep -v) 还包含 -e 字符串 B 或 -e 字符串 C 的那些行。awk 用于使用冒号作为字段分隔符 -F 仅打印第一个字段(文件名)