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

时间:2021-02-10 08:07:22

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”。谢谢!!

4 个解决方案

#1


40  

Try this:

尝试这个:

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

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

说明:grep -lr以递归方式使grep(r)输出包含 的所有文件的列表(l)。 xargs循环遍历这些文件,在每个文件上调用grep -L。 grep -L只会在文件不包含 时输出文件名。

#2


3  

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 -q means run quietly but return an exit code indicating whether a match was found; find can 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 {} \;返回0,然后它将继续执行-not -exec grep -q {} \;。如果它也返回0,它将继续执行-print,它将打印文件的名称。

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

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

#3


1  

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

这些答案似乎是匹配BOTH字符串。以下命令应该更好:

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

#4


1  

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 find predicates as you need) which contain <patternYes>, but do not contain <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 find and add -R to the first grep:

如果您不需要按名称进行过滤(通常需要考虑当前目录中的所有文件),则可以剥离查找并将-R添加到第一个grep:

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

#1


40  

Try this:

尝试这个:

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

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

说明:grep -lr以递归方式使grep(r)输出包含 的所有文件的列表(l)。 xargs循环遍历这些文件,在每个文件上调用grep -L。 grep -L只会在文件不包含 时输出文件名。

#2


3  

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 -q means run quietly but return an exit code indicating whether a match was found; find can 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 {} \;返回0,然后它将继续执行-not -exec grep -q {} \;。如果它也返回0,它将继续执行-print,它将打印文件的名称。

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

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

#3


1  

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

这些答案似乎是匹配BOTH字符串。以下命令应该更好:

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

#4


1  

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 find predicates as you need) which contain <patternYes>, but do not contain <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 find and add -R to the first grep:

如果您不需要按名称进行过滤(通常需要考虑当前目录中的所有文件),则可以剥离查找并将-R添加到第一个grep:

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