【问题标题】:How do I combine my find and grep command to delete the files?如何结合我的 find 和 grep 命令来删除文件?
【发布时间】:2014-09-19 23:51:11
【问题描述】:

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

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 是处理带有空格的文件名所必需的,但现在当我尝试运行该命令时,我收到一条错误消息,指出“二进制文件(标准输入)匹配”。

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

【问题讨论】:

  • 那么grep 命令是否应该在find 找到的路径名上运行?因为这就是它在这里所做的事情。
  • 是的,“find”查找目录中的所有文件,“grep”然后查找 remove_list 文件并在“find”找到的文件中查找任何匹配项。我想删除任何匹配的内容。

标签: bash grep find xargs


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

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

    各种命令的-print0--null-0 参数用于防止由于文件名中的边缘情况(例如具有多个空格和换行符的文件名)而导致的错误。如果您确实必须处理这些问题,问题会变得更加困难,因为您的grep 命令正在尝试过滤名称本身。如果您确实需要这样做,您可能需要切换到可以单独处理每个名称的工具。在具有递归通配符的 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,虽然我认为既然你正在执行多个greps,你可以做一个更简单的最终语法,比如find . -type f -exec bash -c 'grep -qif ./remove_last &lt;&lt;&lt; "{}" &amp;&amp; rm -- "{}"' \;
    【解决方案3】:

    如果您使用的是 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
    

    【讨论】:

      【解决方案4】:

      如果您安装了 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)。你命令行 会爱你的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-05-29
        • 2014-01-18
        • 2018-12-28
        • 1970-01-01
        • 1970-01-01
        • 2015-08-08
        • 1970-01-01
        • 2021-06-07
        相关资源
        最近更新 更多