find . -type f -print0 | xargs --null grep -Z -L 'my string' | xargs --null rm
这将首先使用find打印当前目录和任何子目录中所有文件的名称。这些名称将以null终止符而不是通常的换行符(尝试将输出导向od -c
以查看-print0
参数的效果)。xargs
的 --null
参数告诉它接受以 null 终止的输入。然后,xargs
将在文件名列表上调用grep
。
grep
命令的 -Z
参数就像 find
命令的 -print0
参数一样工作,因此 grep 将以 null 终止方式打印其结果(这就是为什么最后一次调用 xargs
需要一个 --null
选项的原因)。grep
命令的 -L
参数会导致 grep
打印那些没有与正则表达式匹配的命令行中的文件名(这是由 xargs
添加的):
如果您想进行简单匹配而不是使用正则表达式,请添加my string
-F
选项。如果您想使用更强大的正则表达式,则给出一个 -E
参数。使用单引号而不是双引号是个好习惯,因为这样可以保护您免受应用于字符串的任何 shell 魔法(例如变量替换)的影响。xargs
去除前面找到的所有文件。find
命令使用 -exec
参数调用 grep
的问题在于,对于每个文件,grep
都会被调用一次而不是针对整批文件一次像 xargs
那样。如果您有大量文件,则使用 xargs
要快得多。同时也不要试图做类似以下的事情:rm $(some command that produces lots of filenames)
将文件名通过管道传递给xargs
更好,因为它知道命令行的最大限制,并且会多次调用rm
,每次尽可能地传递参数。
请注意,如果不需要处理包含空格和换行符的文件,则此解决方案将更简单。
或者
grep -r -L -Z 'my string' . | xargs --null rm
这也可以(而且更短)。grep
命令的 -r
参数会读取目录中的所有文件,并递归进入任何子目录。如果您还想对文件进行其他测试(如年龄或权限),请使用 find ...
方法。
请注意,任何带有单破折号引导符的单字母参数都可以组合在一起(例如作为 -rLZ
)。但是请注意,find
不使用相同的约定,并具有用单破折号引入的多字母参数。这是由于历史原因而没有被修复,因为这样做会破坏太多脚本。
xargs: illegal option -- -
- user1394GNU grep和bash。
grep -rLZ "$str" . | while IFS= read -rd '' x; do rm "$x"; done
如果需要可移植性,请使用find
解决方案。这样稍微快一点。
-r
参数,它似乎只能默认为文件,除非显式地给出 -
参数。不过,加上 .
可能是一个好主意。我已经添加了它。 - ormaaj[FILE ...]
...但这绝对是在这里发生的事情(即等待输入,没有.
); GNU grep 2.5.4 - Peter.O2.12
。我存储库中提供的最老版本是 2.5.4
。 - ormaajfind . -type f '!' -exec grep -q "my string" {} \; -exec echo rm {} \;
如果预览输出正确,您可以删除echo
。
使用-delete
的等效方法是
find . -type f '!' -exec grep -q "user_id" {} \; -delete
但是这样就无法获得漂亮的预览选项了。
echo
。 - Lev Levitskyshopt -s extglob
rm !(*fix*)
rm !(*fix*|*class*)
Zsh:
要使用它们,请按以下方式启用扩展的 glob zsh shell 选项:
setopt extended_glob
rm -- ^*fix*
rm -- ^(*fix*|*class*)
https://www.tecmint.com/delete-all-files-in-directory-except-one-few-file-extensions/
shopt
命令添加到我的bashrc
中...有什么缺点吗? - pretzlstyle我可以想到几种方法来处理这个问题。这是其中一种:使用 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”进行测试,以确保选择了正确的文件。
find -type f ! -name "*my string*" -exec rm {} \; -print
这个对我有用,如果你能接受删除目录,你可以删除 -f。
myString="keepThis"
for x in `find ./`
do if [[ -f $x && ! $x =~ $myString ]]
then rm $x
fi
done