17

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

4

7 回答 7

15

以下将起作用:

find . -type f -print0 | xargs --null grep -Z -L 'my string' | xargs --null rm

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

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

-Z参数的grep工作方式与 的参数-print0类似find,因此 grep 将打印出以空值结尾的结果(这就是为什么最终调用也xargs需要一个--null选项的原因)。导致在其命令行(已添加)上打印与正则表达式匹配的那些文件的文件名的参数-Lgrepgrepxargs

我的弦

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

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

grep直接从带有参数的find命令调用的问题是每个文件调用一次,而不是像整批文件那样调用一次。如果您有很多文件,这会快得多。也不要试图做类似的事情:-execgrepxargs

rm $(some command that produces lots of filenames)

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

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

或者

grep -r -L -Z 'my string' . | xargs --null rm

也可以(而且更短)。-r参数使其读取目录中的grep所有文件并递归地下降到任何子目录)。find ...如果您还想对文件进行一些其他测试(例如年龄或权限),请使用该方法。

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

于 2012-07-01T15:46:45.013 回答
5

GNU grep 和 bash。

grep -rLZ "$str" . | while IFS= read -rd '' x; do rm "$x"; done

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

于 2012-07-01T08:11:17.663 回答
4

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

find . -type f | grep -v "exclude string" | xargs rm

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

于 2012-07-01T08:02:39.520 回答
3

一种可能是

find . -type f '!' -exec grep -q "my string" {} \; -exec echo rm {} \;

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

等价-delete

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

但是你没有得到很好的预览选项。

于 2012-07-01T08:00:16.040 回答
1

我可以想出几种方法来解决这个问题。这是一个: find 和 grep 生成一个不匹配的文件列表,然后 xargs rm 它们。

find yourdir -type f -exec grep -F -L 'yourstring' '{}' + | xargs -d '\n' rm

这假设 GNU 工具(grep -L 和 xargs -d 是不可移植的),当然没有包含换行符的文件名。它的优点是每个文件不运行 grep 和 rm 一次,所以它会相当快。我建议使用“echo”代替“rm”对其进行测试,以确保它在释放破坏之前选择正确的文件。

于 2012-07-01T08:18:38.800 回答
1

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

重击:

要使用它们,请启用 extglob shell 选项,如下所示:

shopt -s extglob

只需删除所有没有字符串“fix”的文件:

rm !(*fix*)

如果您不想删除所有没有名称“fix”和“class”的文件:

rm !(*fix*|*class*)

Zsh:

要使用它们,请启用扩展 glob zsh shell 选项,如下所示:

setopt extended_glob

删除所有没有字符串的文件,在本例中为“修复”:

rm -- ^*fix*

如果您不想删除所有没有名称“fix”和“class”的文件:

rm -- ^(*fix*|*class*)

可以将其用于扩展,您只需要更改正则表达式:(. zip)、( .doc)等。

以下是来源:

https://www.tecmint.com/delete-all-files-in-directory-except-one-few-file-extensions/

https://codeday.me/es/qa/20190819/1296122.html

于 2019-12-01T14:10:42.140 回答
0

这对我有用,如果您可以删除目录,则可以删除 -f 。

myString="keepThis"
for x in `find  ./`
    do if [[ -f $x && ! $x =~ $myString ]]
        then rm $x
    fi
done
于 2021-11-22T14:58:51.413 回答