删除不包含特定字符串的文件

Hak*_*kim 10 linux bash grep sed

我想找到不包含特定字符串的文件(在目录及其子目录中)并删除这些文件.我怎么能这样做?

Nic*_*ick 10

以下将有效:

find . -type f -print0 | xargs --null grep -Z -L 'my string' | xargs --null rm
Run Code Online (Sandbox Code Playgroud)

这将首先使用find来打印当前目录和所有子目录中所有文件的名称.这些名称使用空终止符而不是通常的换行符分隔符打印(尝试将输出管道化od -c以查看-print0参数的效果.

然后--null参数xargs告诉它接受以null结尾的输入.xargs然后将调用grep文件名列表.

-Z参数的grep作用类似于-print0参数find,因此grep将打印出其结果为null终止(这就是为什么最终调用也xargs需要一个--null选项).导致在其命令行(已添加)上打印与正则表达式匹配的文件名的-L参数:grepgrepxargs

我的字符串

如果你想要没有正则表达式魔法的简单匹配,那么添加-F选项.如果你想要更强大的正则表达式,那么给出一个-E参数.使用单引号而不是双引号是一个好习惯,因为这可以保护您免受任何应用于字符串的shell魔法(例如变量替换)

最后,xargs再次调用以删除您在之前调用中找到的所有文件.

grep直接从find带有-exec参数的命令调用的问题是,grep每个文件调用一次,而不是像整批文件一样调用一次xargs.这是快,如果你有大量的文件.也不要试图做像这样的事情:

rm $(some command that produces lots of filenames)
Run Code Online (Sandbox Code Playgroud)

将它传递给它总是更好,xargs因为它知道最大命令行限制,并且rm每次都会使用尽可能多的参数调用多次.

请注意,此解决方案可以更简单,无需处理包含空格和新行的文件.

另外

grep -r -L -Z 'my string' . | xargs --null rm
Run Code Online (Sandbox Code Playgroud)

也会工作(而且更短).该-r参数grep使其读取目录中的所有文件并递归地下降到任何子目录中.find ...如果要对文件执行其他测试(例如年龄或权限),请使用此方法.

请注意,任何带有单个dash引入程序的单字母参数都可以组合在一起(例如as -rLZ).但请注意,find它不使用相同的约定,并且使用单个破折号引入了多字母参数.这是出于历史原因,并且从未修复过,因为它会破坏太多脚本.


rod*_*ion 5

编辑:这就是你不应该这样做的方式!原因在这里给出。感谢@ormaaj 指出!

find . -type f | grep -v "exclude string" | xargs rm
Run Code Online (Sandbox Code Playgroud)

注意:grep模式将与当前目录中的完整文件路径匹配(请参阅find . -type f输出)


orm*_*aaj 5

GNU grep和bash.

grep -rLZ "$str" . | while IFS= read -rd '' x; do rm "$x"; done
Run Code Online (Sandbox Code Playgroud)

find如果需要可移植性,请使用解决方案.这稍快一点.


Ian*_*nao 4

一种可能性是

find . -type f '!' -exec grep -q "my string" {} \; -exec echo rm {} \;
Run Code Online (Sandbox Code Playgroud)

echo如果此预览的输出看起来正确,您可以删除。

与 等价的-delete

find . -type f '!' -exec grep -q "user_id" {} \; -delete

但这样你就得不到很好的预览选项。