在Linux命令行中,如何删除包含特定字符串的文件?

60

我正在尝试通过Linux CLI在文件中查找电子邮件地址并删除错误的电子邮件。

我可以使用以下命令获取文件:

find . | xargs grep -l email@example.com

但是,我无法弄清楚如何从那里删除它们,因为以下代码不起作用:

rm -f | xargs find . | xargs grep -l email@example.com

8个回答

85

以下是针对您命令的解决方案:

grep -l email@example.com * | xargs rm

或者

for file in $(grep -l email@example.com *); do
    rm -i $file;
    #  ^ prompt for delete
done

1
对于多个文件,您可以使用 grep -l -R --include="*" email@domain.com ./ 来防止通配符添加过多的参数。 - kbtz
这是我使用的命令:sudo grep -lr '/directory/youd/like/to/delete/from/' -e 'text you would like to search' | xargs rm。我相信2grit提到了'-r'表示递归,这对我的情况很有帮助。 - JustinP

80

为了安全起见,我通常将find命令的输出重定向到类似awk的命令中,并创建一个批处理文件,每行都是"rm filename"。

这样你可以在实际运行之前进行检查,并手动修复任何难以使用正则表达式解决的奇怪边缘情况。

find . | xargs grep -l email@example.com | awk '{print "rm "$1}' > doit.sh
vi doit.sh // check for murphy and his law
source doit.sh

我喜欢你的方法,但是对于我来说行不通,因为我需要一个cron job :P 所以我选择了这个 https://dev59.com/vm855IYBdhLWcg3wHwaH#4529188 - Panthro
我该如何计算已删除文件的数量?将命令管道传输到wc -l似乎不起作用。 - readytotaste
1
那么 find . -type f 怎么样? - Paolo

19
您可以使用 find 命令的 -exec -delete 参数,如果 grep 命令成功,则只会删除文件。使用 grep -q 命令可以避免打印任何内容,您可以将 -q 替换为 -l 以查看哪些文件包含了该字符串。
find . -exec grep -q 'email@example.com' '{}' \; -delete

find . -exec grep -q 't-bone@spechal.com' '{}' \; -print 会显示任何内容吗? - OneOfOne
是的,但结果并不如预期。另一方面,find . |grep 't-bone@spechal.com' 却完全正常工作。顺便说一下,我用的是Mac。不过,我的回答解决了我的问题。;) - cregox

3

我喜欢Martin Beckett的解决方案,但发现文件名中有空格会导致问题(谁会在文件名中使用空格呢:pfft)。此外,我想查看匹配的内容,所以我将匹配的文件移动到本地文件夹而不是仅使用“rm”命令删除它们:

# Make a folder in the current directory to put the matched files
$ mkdir -p './matched-files'

# Create a script to move files that match the grep
# NOTE: Remove "-name '*.txt'" to allow all file extensions to be searched.
# NOTE: Edit the grep argument 'something' to what you want to search for.

$ find . -name '*.txt' -print0 | xargs -0 grep -al 'something' | awk -F '\n' '{ print "mv \""$0"\" ./matched-files" }' > doit.sh

Or because its possible (in Linux, idk about other OS's) to have newlines in a file name you can use this longer, untested if works better (who puts newlines in filenames? pfft :D), version:

$ find . -name '*.txt' -print0 | xargs -0 grep -alZ 'something' | awk -F '\0' '{ for (x=1; x<NF; x++) print "mv \""$x"\" ./matched-files" }' > doit.sh

# Evaluate the file following the 'source' command as a list of commands executed in the current context:
$ source doit.sh

注意:我曾经遇到过grep无法匹配utf-16编码文件内部的问题。 在这里可以找到解决方法。如果该网站消失了,你可以使用grep的-a标志,让grep将文件视为文本,并使用一个正则表达式模式来匹配每个扩展字符中的第一个字节。例如,要匹配Entité,请执行以下操作:

grep -a 'Entit.e'

如果那个方法不行,那就试试这个:
grep -a 'E.n.t.i.t.e'

3

尽管Martin的回答很安全,但如果你确定要删除什么,比如在编写脚本时,我使用了这个方法,比其他单行代码更成功:

$ find . | grep -l email@example.com | xargs -I {} rm -rf {}

不过我更喜欢通过名称查找:

$ find . -iname *something* | xargs -I {} echo {}

3
rm -f `find . | xargs grep -li email@example.com`

使用`...`运行命令来找出包含email.@example.comgrep -l列出它们,-i忽略大小写),以便更好地完成工作。然后使用rm-f强制删除 / -i交互式删除)来删除这些文件。


2
find . | xargs grep -l email@example.com

如何移除:
rm -f 'find . | xargs grep -l email@example.com'

1
欢迎来到Stack Overflow!虽然这段代码可能解决了问题,但包括解释真的有助于提高您的帖子质量。请记住,您正在为未来的读者回答问题,而这些人可能不知道您提出代码建议的原因。- 来自审查 - Ferrybig
查找有效的工作,删除无效的(CentOS 6) - user2455079

1

快速高效。将find_files_having_this_text替换为您想要搜索的文本。

grep -Ril 'find_files_having_this_text'  . |  xargs rm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接