如何在Linux上的Bash中一次删除多个文件?


103

我在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

还有另一种方法,以便我可以立即删除所选文件吗?


4
还有“说GNU / Linux,而不仅仅是Linux”,我听到后座声音很大。
鲍里斯·斯蒂尼克

8
顺便说一句,为什么要使用the-rf?这些是文件夹吗?f表示强制,r表示递归。如果它只是一个文件但受到警告,它将起作用,每次您想要删除某物时都使用-rf是非常(非常)(非常非常)危险的。(你应该添加标记“庆典”,因为“Linux”是太宽。
Depado

@BorisStitnicky-我很好奇为什么GNU需要它?
user66001 2013年

2
@ user66001:对于GNU项目对此事的意见:gnu.org/gnu/linux-and-gnu.html。我对此没有立场,至少在这里没有立场,这不是辩论的地方。
基思·汤普森

2
@BorisStitnicky-无需辩论,完全毫无头绪,并且该链接为我提供了我所需要的信息级别+1
user66001 2013年

Answers:


159

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

您的确切情况将通过括号扩展来处理,如下所示:

$ 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

重要的是要注意,这种扩展是由外壳完成的,rm甚至在加载之前。


如果您希望将来还原文件,请不要使用“ rm”。可以使用“ rm-trash”实用程序: github.com/nateshmbhat/rm-trash
Natesh bhat

75

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

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

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

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

有关更多详细信息,请参见有关文件名扩展的Bash手册页。


非常有用,但它并不要求确认删除。请注意。
nuriselcuk

1
@nuriselcuk,您可以添加-i,以获取每个要删除文件的确认。
费利佩·罗梅罗

在运行Amazon Linux 1的AWS Ec2-Instance上像魅力一样工作:)谢谢。
凯尔·布​​莱恩汀汀

41

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

$ 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

正则表达式比通配符更强大。您可以将的输出提供greprm -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 barrm -f 'foo bar'


8

只需在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来到这里的人们来说,它更加友好。
ATLief '16

5

通配符可以很好地实现此目的,尽管为了安全起见,最好尽量减少使用通配符,因此应遵循以下原则:

rm -rf abc.log.2012-*

尽管从外观上看,这些只是单个文件吗?如果这些项目都不是目录,则不必使用递归选项,因此最好不要使用它,只是出于安全考虑。


2

我不是Linux专家,但我相信您想将输出文件列表发送到xargs rm -rf。我过去使用过类似的方法,效果很好。首先在示例目录上进行测试!

编辑-根据出现的其他答案,我可能误会了。如果可以使用通配符,那就太好了。我以为您显示的原始列表是由一个程序生成的,以便您进行“选择”,因此我认为xargs应该使用管道。


-1

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

rm -rf /log/*
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.