ChatGPT解决这个技术问题 Extra ChatGPT

如何查找不包含给定字符串模式的文件?

如何找出当前目录中文件包含单词foo(使用grep)?


t
t0r0X

如果您的 grep 具有 -L(或 --files-without-match)选项:

$ grep -L "foo" *

正如在其他地方指出的那样,默认情况下 ack 有助于避免使用 .svn (颠覆)文件。
@GuruM 这可以在 GNU grep 中通过导出变量 GREP_OPTIONS='--exclude-dir=.svn --exclude-dir=.git' 来完成 :^)
或使用 ag 的等效项:ag -L 'foo'
如果您想查找名称中没有多个内容的文件怎么办。 grep -L "foo,bar,baz" * ?
像魔术一样工作!提示:使用 -rL 而不是 -L 来匹配子目录
A
Adrian

您可以单独使用 grep 来完成(无需查找)。

grep -riL "foo" .

这是grep上使用的参数的解释

     -L, --files-without-match
             each file processed.
     -R, -r, --recursive
             Recursively search subdirectories listed.

     -i, --ignore-case
             Perform case insensitive matching.

如果您使用 l(小写),您将得到相反的结果(匹配的文件)

     -l, --files-with-matches
             Only the names of files containing selected lines are written

n
nbro

看看ack。它会自动为您排除 .svn,为您提供 Perl 正则表达式,并且是单个 Perl 程序的简单下载。

ack 中,您正在寻找的内容应该是等价的:

ack -L foo

n
nbro

以下命令为我提供了所有不包含模式 foo 的文件:

find .  -not  -ipath '.*svn*' -exec  grep  -H -E -o -c  "foo"  {} \; | grep 0

您想将末尾的 grep 0 更改为 grep 0$ (否则您会在文件名中包含字符 0 的文件上得到错误的匹配)。
@clouseau 基本上是对的......但是,grep '0$' 也会匹配 10 行的倍数的文件!最后需要 grep ':0$' 来检查行尾是否有明确的 ':0'。然后你只会得到零行匹配的文件。
我使用的 UNIX 没有带有这些选项的 find 或 grep 版本,所以我不得不使用其他评论中建议的“ack”命令。
非常无用,因为 find 必须查找所有文件,包括那些包含“foo”的文件,然后在第二个进程中丢弃它们。对于正在寻找的大量文件将无法正常工作。应该提供使用内置 find 参数的解决方案。
n
nbro

以下命令不需要 find 使用第二个 grep 过滤掉 svn 文件夹。

grep -rL "foo" ./* | grep -v "\.svn"

Z
Zak

如果您使用的是 git,这将搜索所有跟踪的文件:

git grep -L "foo"

如果您打开了 ** 子目录通配符,您可以在跟踪文件的子集中搜索(.bashrc 中的 shopt -s globstar,请参阅 this):

git grep -L "foo" -- **/*.cpp

n
nbro

您实际上将需要:

find .  -not  -ipath '.*svn*' -exec  grep  -H -E -o -c  "foo"  {} \; | grep :0\$

n
nbro

我很幸运

grep -H -E -o -c "foo" */*/*.ext | grep ext:0

我对 grep -v 的尝试只是给了我所有没有“foo”的行。


G
Gruffy

问题

我需要重构一个使用 .phtml 文件使用内联 PHP 代码写出 HTML 的大型项目。我想改用 Mustache 模板。我想找到任何不包含字符串 new Mustache.phtml giles,因为它们仍然需要重写。

解决方案

find . -iname '*.phtml' -exec grep -H -E -o -c 'new Mustache' {} \; | grep :0$ | sed 's/..$//'

解释

管道前:

寻找

find . 递归查找文件,从这个目录开始

-iname '*.phtml' 文件名必须包含 .phtmli 使其不区分大小写)

-exec 'grep -H -E -o -c 'new Mustache' {}' 对每个匹配的路径运行 grep 命令

格雷普

-H 始终使用输出行打印文件名标题。

-E 将模式解释为扩展的正则表达式(即强制 grep 表现为 egrep)。

-o 仅打印行的匹配部分。

-c 仅将选定行的计数写入标准输出。

这将为我提供以 .phtml 结尾的所有文件路径的列表,并计算字符串 new Mustache 在每个路径中出现的次数。

$> find . -iname '*.phtml$' -exec 'grep -H -E -o -c 'new Mustache' {}'\;

./app/MyApp/Customer/View/Account/quickcodemanagestore.phtml:0
./app/MyApp/Customer/View/Account/studio.phtml:0
./app/MyApp/Customer/View/Account/orders.phtml:1
./app/MyApp/Customer/View/Account/banking.phtml:1
./app/MyApp/Customer/View/Account/applycomplete.phtml:1
./app/MyApp/Customer/View/Account/catalogue.phtml:1
./app/MyApp/Customer/View/Account/classadd.phtml:0
./app/MyApp/Customer/View/Account/orders-trade.phtml:0

第一个管道 grep :0$ 过滤此列表以仅包含以 :0 结尾的行:

$> find . -iname '*.phtml' -exec grep -H -E -o -c 'new Mustache' {} \; | grep :0$

./app/MyApp/Customer/View/Account/quickcodemanagestore.phtml:0
./app/MyApp/Customer/View/Account/studio.phtml:0
./app/MyApp/Customer/View/Account/classadd.phtml:0
./app/MyApp/Customer/View/Account/orders-trade.phtml:0

第二个管道 sed 's/..$//' 去掉每行的最后两个字符,只留下文件路径。

$> find . -iname '*.phtml' -exec grep -H -E -o -c 'new Mustache' {} \; | grep :0$ | sed 's/..$//'

./app/MyApp/Customer/View/Account/quickcodemanagestore.phtml
./app/MyApp/Customer/View/Account/studio.phtml
./app/MyApp/Customer/View/Account/classadd.phtml
./app/MyApp/Customer/View/Account/orders-trade.phtml

D
Daniel J.

当您使用 find 时,您有两个基本选项:在 find 完成搜索后过滤结果或使用一些内置选项,这将阻止 find 考虑那些与某些给定模式匹配的文件和目录。

如果您对大量文件和目录使用前一种方法。您将使用大量 CPU 和 RAM 只是为了将结果传递给第二个进程,而第二个进程又会通过使用大量资源来过滤掉结果。

如果您使用作为 find 参数的 -not 关键字,您将阻止考虑与后面的 -name 或 -regex 参数上的字符串匹配的任何路径,这将更加有效。

find . -not -regex ".*/foo/.*" -regex ".*"

然后,任何未被 -not 过滤掉的路径都将被后续的 -regex 参数捕获。


这会搜索不包含特定模式的文件名,对吗?我认为 OP 意味着文件内容不包含某种模式
嗯,这个问题本身有点模糊,我只是这样解释的。有些人在寻找排除文件名时肯定会找到这个线程。
J
JMD

当 grep 没有 -L 选项(例如 IBM AIX)时的另一种选择,只有 grep 和 shell :

for file in * ; do grep -q 'my_pattern' $file || echo $file ; done

u
user6305682

我的 grep 没有任何 -L 选项。我确实找到了解决方法来实现这一点。

这些想法是:

将所有包含应得字符串的文件名转储到 txt1.txt。将目录中的所有文件名转储到一个txt2.txt。用 diff 命令区分 2 个转储文件。 grep 'foo' *.log |切-c1-14 | uniq > txt1.txt grep * *.log |切-c1-14 | uniq > txt2.txt 差异 txt1.txt txt2.txt | grep >"


我忘记了命令,但实际上你可以在两个输出流之间做一个 diff 而不是转储文件名(我认为你用括号括住命令,并且那里也有一个尖括号),如果你的系统支持它,我猜这是问题,因为它不支持 grep -L
z
zandeep

find *20161109* -mtime -2|grep -vwE "(TRIGGER)"

您可以在“find”下指定过滤器,在“grep -vwE”下指定排除字符串。如果您还需要过滤修改后的时间,请在 find 下使用 mtime。


这似乎向我显示了所有没有字符串的行,OP 只要求提供文件名。
d
dfrib

打开错误报告

正如@tukan 评论的那样,Ag 有一个关于 -L/--files-without-matches 标志的开放错误报告:

ggreer/the_silver_searcher: #238 - --files-without-matches 无法正常工作

由于错误报告进展甚微,因此不应依赖下面提到的 -L 选项,只要错误尚未解决。请改用此线程中介绍的不同方法。引用错误报告的评论[强调我的]:

对此有何更新? -L 完全忽略文件第一行的匹配项。似乎如果这不会很快得到解决,则应该完全删除该标志,因为它实际上根本不像宣传的那样工作。

Silver Searcher - Ag(预期功能 - 参见错误报告)

作为 grep 的强大替代品,您可以使用 The Silver Searcher - Ag

一个类似ack的代码搜索工具,重点是速度。

查看 man ag,我们发现 -L--files-without-matches 选项:

... 选项 ... -L --files-without-matches 仅打印不包含匹配项的文件的名称。

即,递归从当前目录搜索不匹配 foo 的文件:

ag -L foo

要仅在 当前 目录中搜索与 foo 不匹配的文件,只需为递归指定 --depth=0

ag -L foo --depth 0

由于 -L 错误 - github.com/ggreer/the_silver_searcher/issues/238,这有时会失败
@tukan 感谢您的提示。我已经更新了答案;选择不删除答案,而是打开有关错误的信息。
A
ARIF MAHMUD RANA

这可能对其他人有所帮助。我混合了文件 Gotest 文件。但我只需要 .go 个文件。所以我用

ls *.go | grep -v "_test.go"

-v, --invert-match 选择不匹配的行见 https://stackoverflow.com/a/3548465

也可以将它与 vscode 一起使用从终端打开所有文件

code $(ls *.go | grep -v "_test.go")

这会按名称过滤文件,而不是内容
@MathieuLongtin 是的,我明确表示I have mix of files Go and with test files. But I only need .go files. So I used我只是添加了这个来帮助我使用的其他人。
你在回答一个非常不同的问题
a
akostadinov

为了完整起见,ripgrep 版本:

rg --files-without-match "pattern"

您可以结合文件类型和搜索路径,例如

rg --files-without-match -t ruby "frozen_string_literal: true" app/

Z
Zong
grep -irnw "filepath" -ve "pattern"

或者

grep -ve "pattern" < file

上面的命令会给我们结果,因为 -v 找到正在搜索的模式的逆


这将打印不包含模式的行。您可以添加 -l 选项以仅打印文件名;但这仍然会打印包含 any 行但不包含该模式的任何文件的名称。我相信 OP 想要找到不包含任何包含模式的行的文件。
您提供的命令列出了“文件路径”中的文件及其所有不包含“模式”的行。
n
nbro

以下命令可以帮助您过滤包含子字符串“foo”的行。

cat file | grep -v "foo"

这将打印不匹配的行,而不是在任何行上不包含匹配的文件的名称。雪上加霜,它作为一个useless use of cat