如何结合使用find和grep命令删除文件?

时间:2014-07-28 17:52:07

标签: bash grep find xargs

我目前有以下命令生成文件列表:

find . -type f | grep -i -f ./remove_list

此命令读取名为" remove_list"的文件。其中包含我想在find命令的输出中找到的术语列表(实际上是正则表达式)。

上面的命令工作正常,但我不明白现在如何删除找到的每个文件(特别是因为其中一些文件会包含空格)。

我以为我可以这样做:

find . -type f -print0 | grep -i -f ./remove_list | xargs -0 rm

据我所知,-print0和-0是处理带有空格的文件名所必需的,但现在当我尝试运行命令时,我收到一条错误消息,说明"二进制文件(标准输入)匹配&#34 ;

如何从文件中读取多个(正则表达式)术语,以便它们可以在查找语句中用作参数?

4 个答案:

答案 0 :(得分:2)

您只需要grep输出文件列表。 Grep并不知道这些是文件:它只是将它们视为数据流。如果文件本身在名称中没有换行符并且通常是空白安全的,那么您可以这样做:

find . -type f | grep -if ./remove_list | xargs rm

各种命令的-print0--null-0参数用于防止由于文件名中的边缘情况引起的错误,例如具有多个空格和换行符的文件名。如果您真的必须处理这些问题,问题会变得更加困难,因为您的grep命令正在尝试过滤名称本身。如果您确实需要这样做,您可能希望切换到可以单独处理每个名称的工具。在具有递归globbing的shell中(例如bash 4):

shopt -s globstar
for f in **/*; do
    # check if "$f" is a file and grep matches its name
    if [[ -f $f ]] && grep -qif ./remove_list <<< "$f"; then
        rm "$f"
    fi
done

与往常一样,您可以在find和具有相同逻辑的标准shell中模仿它,但有点丑陋:

find . -type f -exec bash -c 'for f; do
    if printf '%s\n' "$f" | grep -qif ./remove_list; then
        rm "$f"
    fi
done' _ {} +

答案 1 :(得分:2)

如果您的第一个命令找到所有文件,您可以通过while循环传递输出以删除每个文件。

find . -type f | grep -i -f ./remove_list | while read line; do rm "$line"; done

答案 2 :(得分:0)

如果你正在使用GNU grep。您可以使用-Z

   -Z, --null
          Output a zero byte (the ASCII NUL character) instead of the character that normally follows a file name.  For example,
          grep -lZ outputs a zero byte after each file name instead of the usual newline.  This option makes the output
          unambiguous, even in the presence of file names containing unusual characters like newlines.  This option can be used
          with commands like find -print0, perl -0, sort -z, and xargs -0 to process arbitrary file names, even those that contain
          newline characters.

您还需要输入-z

   -z, --null-data
          Treat the input as a set of lines, each terminated by a zero byte (the ASCII NUL character) instead of a newline.  Like
          the -Z or --null option, this option can be used with commands like sort -z to process arbitrary file names.

所以你的命令可能如下:

find . -type f -print0 | grep -z -Z -i -f ./remove_list | xargs -0 rm

答案 3 :(得分:0)

如果你安装了GNU Parallel:

find . -type f | grep -i -f ./remove_list | parallel rm

如果没有为您的系统打包,则应在10秒内安装:

(wget -O - pi.dk/3 || curl pi.dk/3/ || fetch -o - http://pi.dk/3) | bash

要了解更多信息:观看介绍视频,以便快速了解: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

完成教程(man parallel_tutorial)。你命令行 会爱你的。