全部
我的 Linux 机器中有以下两个文件,我想找出包含“word1”但不包含“word99”的文件
file1.txt
word1
word2
word3
word4
word5
file2.txt
word1
word2
word3
word99
我一直在使用以下命令来获取包含“word1”的文件,但找不到任何有关如何修改它以获取包含“word1”但不包含“word99”的文件名的信息
find . -name '*.*' -exec grep -r 'word1' {} \; -print > output.txt
任何指点都会有帮助。
谢谢桑迪
答案1
$ grep -lr 'word1' * | xargs grep -L 'word99'
file1.txt
在哪里:
-l, --files-with-matches
Only the names of files containing selected lines are written
to standard output.
-R, -r, --recursive
Recursively search subdirectories listed.
-L, --files-without-match
Only the names of files not containing selected lines are written
to standard output.
在管道之前的命令的第一部分中,我们得到:
$ grep -lr 'word1' *
file1.txt
file2.txt
上述命令递归解析子目录内的文件,并列出包含单词word1
、 iefile1.txt
和 的文件file2.txt
。
稍后在第二部分中| xargs grep -L 'word99'
,管道发送file1.txt
和file2.txt
作为输入到,xargs
并将它们grep
作为参数提供给。然后列出不包含使用该选项grep
的文件,即。word99
-L
file1.txt
这里我们需要xargs
,因为在命令的第一部分,我们得到了file1.txt
和file2.txt
作为 stdout 上的输出。我们需要解析这些文件的内容,而不是字符串file1.txt
和file2.txt
。
以下命令也给出相同的结果(反转我们搜索/排除字符串的方式):
$ grep -Lr 'word99' * | xargs grep -l 'word1'
file1.txt
答案2
这将查找包含以下内容的文件word1
:
$ find . -name '*.*' -type f -exec grep -q 'word1' {} \; -print
./file1.txt
./file2.txt
这将查找包含word1
以下内容的文件:不是 word99
:
$ find . -name '*.*' -type f -exec grep -q 'word1' {} \; '!' -exec grep -q 'word99' {} \; -print
./file1.txt
要将输出保存在文件中:
find . -name '*.*' -type f -exec grep -q 'word1' {} \; '!' -exec grep -q 'word99' {} \; -print >output.txt
对于包含 的文件,测试-exec grep -q word99 {} \;
将返回 True word99
。我们!
在它前面加上 来否定返回值。因此,! -exec grep -q word99 {} \;
对于包含 的文件,测试将返回 True不是有word99
。!
用单引号引起来是因为,如果打开了历史扩展,!
可以是 shell 活动字符。
笔记:
-q
添加了选项以使其grep
安静。使用-q
,grep 将设置正确的退出代码,但不会在 stdout 上显示匹配的行。-type f
添加测试以便find
它仅返回常规文件的名称。
答案3
您的问题标题说的是“包含单词的文件”。但是,在您的问题中,您确实提到了“获取包含单词的文件名”。这是两码事。幸运的是,它们都相当简单,所以我将简单地向您展示两者。
查找包含单词的文件:
grep -iR“单词1”。
-i 表示忽略大小写。-R 是递归的(表示搜索子目录)。(OpenBSD 记录了大写字母,它与 ls 更相似,所以我更喜欢大写字母而不是 -r。)句点指定从哪里开始查找。
查找包含单词的文件名:
查找 .-iname "单词1“
-iname 是“name”的不区分大小写的版本。
句点指定从哪里开始查找。当前目录通常是一个不错的选择。
注意:您引用了“。“在您的一个示例中。这对于 DOS 来说很棒,在 Microsoft Windows 中通常也很好,但对于 Unix 环境来说,这是一个非常坏的习惯。看到这一点,我觉得您熟悉 Windows。好吧,请理解,在 Windows 中,“FIND”(或“find”)定位文件中的文本。Unix 则不同:“grep”定位文件中的文本,“find”定位文件名。
现在,要排除单词 99,并将其放在文本文件中,请添加以下文本:
| grep -v word99 >> 输出.txt
这是管道键,几乎总是 Shift-Backslash。
因此,举个例子,如果您想同时执行这两项操作,请使用:
grep -iR "word1" . | grep -v word99 >> output.txt
查找 . -iname "单词1“|grep -v word99>>输出.txt”
管道符之前的部分将运行命令,并将输出发送到 Unix 样式的管道。然后,内容从管道发送到下一个命令的标准输入。grep -v 将查看它收到的标准输入,并排除您想要的内容。grep -v 将其余结果发送到其标准输出。>> 将把前一个命令的标准输出重定向到指定文本文件的末尾。
您之所以没有在“find”命令中看到有关如何排除文本的文档选项,是因为 Unix 在设计时就非常注重简化程序,并使用管道技术来产生复杂的效果。在 Microsoft 环境中,旧的 Microsoft 代码在管道处理方面特别麻烦,因此程序基本上试图将更多功能整合到每个程序中。一方面,这对最终用户来说似乎更简单(所有功能都内置),但这种方法缺乏一致性。当您使用 Unix 时,不要害怕管道:一旦您习惯了它,您可能会发现它大大简化了事情,但因为您可以在许多情况下使用简单的工具,所以您不需要一遍又一遍地重新学习简单的技术(针对每个不同的程序)。