【问题标题】:Remove files not containing a specific string删除不包含特定字符串的文件
【发布时间】:2012-07-02 01:59:52
【问题描述】:

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

【问题讨论】:

  • @SivaCharan 是的......从存在:)
  • 删除我的意思是:删除

标签: linux bash sed grep


【解决方案1】:

以下将起作用:

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

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

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

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

我的字符串

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

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

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

rm $(some command that produces lots of filenames)

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

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

或者

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

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

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

【讨论】:

  • 如果我们想检查像grep -r -L -Z 'Astring' OR 'Bstring' OR 'Cstring' * | xargs --null rm这样的字符串列表?
  • 您可以使用 grep 的 egrep 形式,然后像这样搜索替代字符串: egrep ... 'Astring|Bstring|Cstring' ...
  • @user1394 你遇到了什么问题?
  • xargs: illegal option -- -
  • @user1394 你能告诉我你在输入什么以及你看到的响应吗
【解决方案2】:

GNU grep 和 bash。

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

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

【讨论】:

  • @Peter.O 奇怪我无法重现。如果使用-r,它似乎别无选择,只能默认为文件,除非明确给出-。不过,. 可能是个好主意。已添加。
  • 当你添加. 时,我已经删除了我的原始评论,你肯定已经看到了,但我也有点困惑,因为'man grep' 显示[FILE ...] for最后一个选项......但这绝对是这里发生的事情(即等待输入,没有.); GNU grep 2.5.4
  • 默认的“.” for grep -r 是最近在 grep 2.11 中添加的。而且 GNU 不太尊重手册页。
  • 啊,2.12 在这里。 2.5.4 是我的仓库中可用的最旧的。
【解决方案3】:

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

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

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

【讨论】:

  • 投反对票的不是我,但仅供参考,可能是由于xargs
  • @ormaaj OMG!我以前经常使用这个(xx;)感谢您指出。
  • 这个命令真的很棒,它运行得又快又完美
【解决方案4】:

一种可能性是

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

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

-delete 等价的是

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

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

【讨论】:

  • 这对我不起作用。我可以看到 rm 命令在命令行中运行,但是在完成命令后没有任何内容被删除。所有文件确实存在。我手动检查了文件,发现其中一些不包含字符串...
  • 您是否要识别 namecontent 中没有特定字符串的文件似乎有些混淆。这个答案(使用 -v 而不是 -q)将查看文件名。我的回答看内容。
  • @Hakim 命令回显而不是实际删除。在删除之前尝试是一种很好的做法。如果列出的文件正确,请删除单词echo
  • 这将找到包含给定字符串的文件...而不是NOT containing。出于这个原因,我给了-1,因为这个答案可能会毁了某人的生活。我也在标记。
  • @Flash - 真的,将! 添加到find 的参数以颠倒意义有多难?这不像任何人会盲目地复制答案而不试图理解它是做什么的。而echo rm 几乎不会毁掉任何人的生活。
【解决方案5】:

我可以想出几种方法来解决这个问题。这里有一个: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”对其进行测试,以确保它在释放破坏之前选择正确的文件。

【讨论】:

  • 这个也不是xargs。如果使用 xargs,-0 是唯一的方法。
  • -d '\n' 是一个足够好的方法,直到你得到一个包含换行符的文件名。它禁用了大多数 xargs 愚蠢,就像 -0 一样。不过很高兴了解 grep -Z。
  • 一个包含换行符的文件名?键盘上有一只猫的家伙怎么样?他不能像这样输入长命令!啊,这太疯狂了。但你可以在 youtube 上找到。
  • 是的,只要文件名正常就可以了。
  • 好的。这对我来说很好。我删除了文件名中的空格并检查了这个脚本。谢谢艾伦。
【解决方案6】:

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

重击:

要使用它们,请启用 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

【讨论】:

    【解决方案7】:

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

    myString="keepThis"
    for x in `find  ./`
        do if [[ -f $x && ! $x =~ $myString ]]
            then rm $x
        fi
    done
    

    【讨论】:

      猜你喜欢
      • 2020-07-27
      • 2012-03-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-18
      • 2020-01-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多