我在 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
有没有其他方法可以一次性删除选中的文件?
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
加载之前由 shell 完成的。
使用通配符 (
*
) 来匹配多个文件。
例如,以下命令将删除所有名称以
abc.log.2012-03-
开头的文件。
rm -f abc.log.2012-03-*
我建议运行
ls abc.log.2012-03-*
列出文件,以便您可以在运行 rm
命令之前看到要删除的内容。
有关更多详细信息,请参阅有关 文件名扩展的 Bash 手册页。
如果要删除名称与特定形式匹配的所有文件,通配符(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'
.
只需在 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
通配符可以很好地解决此问题,但为了安全起见,最好尽可能少地使用通配符,因此大致如下:
rm -rf abc.log.2012-*
虽然从表面上看,这些只是单个文件吗?如果这些项目都不是目录,则不需要递归选项,因此最好不要使用它,只是为了安全起见。
我不是 Linux 专家,但我相信您想将输出文件列表通过管道传输到
xargs rm -rf
。我过去使用过类似的东西,效果很好。首先在示例目录上进行测试!
编辑 - 根据出现的其他答案,我可能误解了。如果您可以使用通配符,那就太好了。我假设您显示的原始列表是由程序生成的,以便为您提供“选择”,所以我认为通过管道传输到
xargs
将是正确的选择。
如果您想一次删除属于某个目录的所有文件。 例如: 您的目录名称是“log”,“log”目录包括abc.log.2012-03-14,abc.log.2012-03-15,...等文件。您必须位于日志目录之上并且:
rm -rf /log/*
我想一步删除多个未被通配符覆盖的文件是什么?