【问题标题】:How to delete multiple files at once in Bash on Linux?如何在 Linux 上的 Bash 中一次删除多个文件?
【发布时间】:2012-05-17 23:39:26
【问题描述】:

我在 Linux 服务器上有这个文件列表:

abc.log.2012-03-14
abc.log.2012-03-27
abc.log.2012-03-28
abc.log.2012-03-29
abc.log.2012-03-30
abc.log.2012-04-02
abc.log.2012-04-04
abc.log.2012-04-05
abc.log.2012-04-09
abc.log.2012-04-10

我一直在删除选定的日志文件,使用命令rm -rf 见下文:

rm -rf abc.log.2012-03-14
rm -rf abc.log.2012-03-27
rm -rf abc.log.2012-03-28

有没有其他方法可以一次性删除选中的文件?

【问题讨论】:

  • 还有“说 GNU/Linux,而不仅仅是 Linux”,我听到有人从后座发出雷鸣般的声音。
  • 顺便问一下,为什么要使用 -rf ?这些是文件夹吗? f 是强制,r 是递归。如果它只是一个文件但被警告,它会起作用,每次你想删除某些东西时使用 -rf 是非常(非常)(非常非常)危险的。 (并且您应该添加标签“bash”,因为“linux”太宽了。
  • @BorisStitnicky - 我很好奇为什么需要GNU
  • @user66001:GNU 项目对此事的看法:gnu.org/gnu/linux-and-gnu.html。我对此事不持任何立场,至少在这里不持立场,而且这里不是辩论它的地方。
  • @BorisStitnicky - 无需辩论,完全没有头绪,该链接为我提供了我正在寻找的信息级别 +1

标签: linux bash rm


【解决方案1】:

如果要删除名称与特定格式匹配的所有文件,通配符(glob 模式)是最直接的解决方案。一些例子:

$ rm -f abc.log.*             # Remove them all
$ rm -f abc.log.2012*         # Remove all logs from 2012
$ rm -f abc.log.2012-0[123]*  # Remove all files from the first quarter of 2012

正则表达式比通配符更强大;您可以将grep 的输出提供给rm -f。例如,如果一些文件名以"abc.log" 开头,而一些以"ABC.log" 开头,则grep 允许您进行不区分大小写的匹配:

$ rm -f $(ls | grep -i '^abc\.log\.')

如果任何文件名包含有趣的字符(包括空格),这将导致问题。小心点。

当我这样做时,我首先运行ls | grep ... 命令并检查它是否产生了我想要的输出——尤其是如果我使用的是rm -f

$ ls | grep -i '^abc\.log\.'
(check that the list is correct)
$ rm -f $(!!)

其中!! 扩展为上一个命令。或者我可以键入向上箭头或 Ctrl-P 并编辑上一行以添加 rm -f 命令。

这假设您使用的是 bash shell。其他一些 shell,尤其是 csh 和 tcsh 以及一些旧的 sh 派生的 shell,可能不支持 $(...) 语法。您可以使用等效的反引号语法:

$ rm -f `ls | grep -i '^abc\.log\.'`

$(...) 语法更容易阅读,如果你真的有野心,它可以嵌套。

最后,如果您要删除的文件子集不能用正则表达式轻松表达,我经常使用的一个技巧是将文件列出到临时文本文件中,然后对其进行编辑:

$ ls > list
$ vi list   # Use your favorite text editor

然后我可以手动编辑list 文件,只留下我想要删除的文件,然后:

$ rm -f $(<list)

$ rm -f `cat list`

(再次假设所有文件名都不包含有趣的字符,尤其是空格。)

或者,在编辑list 文件时,我可以将rm -f 添加到每一行的开头,然后:

$ . ./list

$ source ./list

编辑文件也是在必要时添加引号的机会,例如将 rm -f foo bar 更改为 rm -f 'foo bar'

【讨论】:

    【解决方案2】:

    如果您想一次删除属于某个目录的所有文件。 例如: 您的目录名称是“log”,“log”目录包括 abc.log.2012-03-14、abc.log.2012-03-15、...等文件。您必须位于日志目录之上并且:

    rm -rf /log/*
    

    【讨论】:

      【解决方案3】:

      只需在 sublime 中使用多行选择将所有文件合并为一行,并在每个文件名之间添加一个空格,然后在列表开头添加rm。当您要删除的文件名中没有模式时,这非常有用。

      [$]> rm abc.log.2012-03-14 abc.log.2012-03-27 abc.log.2012-03-28 abc.log.2012-03-29 abc.log.2012-03-30 abc.log.2012-04-02 abc.log.2012-04-04 abc.log.2012-04-05 abc.log.2012-04-09 abc.log.2012-04-10
      

      【讨论】:

      • 这应该是公认的答案,因为它明确回答了提出的问题。它对从 Google 来到这里的人更友好。
      【解决方案4】:

      通配符可以很好地解决这个问题,尽管为了安全起见,最好尽可能少地使用通配符,所以大致如下:

      rm -rf abc.log.2012-*
      

      虽然从表面上看,这些只是单个文件吗?如果这些项目都不是目录,则不需要递归选项,因此最好不要使用它,只是为了安全。

      【讨论】:

        【解决方案5】:

        Bash 支持各种通配符和扩展。

        您的具体情况将由brace expansion 处理,如下所示:

        $ rm -rf abc.log.2012-03-{14,27,28}
        

        上面将扩展为一个包含所有三个参数的命令,并且相当于输入:

        $ rm -rf abc.log.2012-03-14 abc.log.2012-03-27 abc.log.2012-03-28
        

        请务必注意,此扩展是由 shell 完成的,甚至在 rm 加载之前。

        【讨论】:

        【解决方案6】:

        我不是 linux 专家,但我相信您希望将输出文件列表通过管道传输到 xargs rm -rf。我过去使用过类似的东西,效果很好。先在示例目录上测试!

        编辑 - 根据出现的其他答案,我可能误解了。如果您可以使用通配符,那就太好了。我假设您显示的原始列表是由程序生成的,以便为您提供“选择”,因此我认为通过管道发送到 xargs 将是可行的方法。

        【讨论】:

          【解决方案7】:

          使用通配符 (*) 匹配多个文件。

          例如,下面的命令将删除所有名称以abc.log.2012-03-开头的文件。

          rm -f abc.log.2012-03-*
          

          我建议运行 ls abc.log.2012-03-* 来列出文件,以便在运行 rm 命令之前查看要删除的内容。

          有关更多详细信息,请参阅 filename expansion 上的 Bash 手册页。

          【讨论】:

          • 非常有用,但它不要求确认删除。请注意。
          • @nuriselcuk 您可以添加 -i 以确认每个被删除的文件。
          • 在运行 Amazon Linux 1 的 AWS Ec2-Instance 上表现出色 :) 谢谢。
          猜你喜欢
          • 2013-03-11
          • 2021-05-01
          • 1970-01-01
          • 2014-11-23
          • 2012-08-23
          • 1970-01-01
          • 1970-01-01
          • 2023-03-02
          • 1970-01-01
          相关资源
          最近更新 更多