删除Linux中没有以下扩展名的所有文件

Tik*_*ike 19 linux ssh rm find

我有一个扩展名列表:

avi,mkv,wmv,mp4,mp5,flv,M4V,mpeg,mov,m1v,m2v,3gp,avchd
Run Code Online (Sandbox Code Playgroud)

我想删除没有以下扩展名的所有文件以及linux中目录中没有扩展名的文件.

如何使用rm linux命令执行此操作?

jay*_*ngh 33

您首先必须找出不包含这些扩展名的文件.您可以使用该find命令轻松完成此操作.您可以构建以下命令 -

find /path/to/files ! -name "*.avi" -type f -exec rm -i {} \;
Run Code Online (Sandbox Code Playgroud)

您也可以使用-regex而不-name是以复杂的搜索模式提供.!是否定了搜索.因此,它将有效地列出那些不包含这些扩展名的文件.

这样做很好,rm -i因为它会在删除之前列出所有文件.如果您的列表是全面的,那么可能会变得乏味,因此您可以决定是否包含它.

使用它删除大量文件可能很危险.删除后,您永远无法取回它们.因此,请确保在find没有第rm一个命令的情况下运行该命令,然后再删除它们.

更新:

如评论中所述aculich,您还可以执行以下操作 -

find /path/to/files ! -name "*.avi" -type f -delete
Run Code Online (Sandbox Code Playgroud)

-type f将确保它只会finddelete 常规文件,不会触及任何目录,sym链接等.

  • 我建议使用`-delete`而不是`-exec rm`; 你的实现可能有它,所以使用它! (6认同)
  • 您可能还希望将`-type f`添加到仅列出具有这些扩展名而不是目录的文件(尽管在这个具体示例中可能不太可能). (4认同)

acu*_*ich 12

您可以使用快速而脏的rm命令来完成您想要的任务,但请记住,它容易出错,不便携,危险并且有严重的限制.

正如其他人所建议的那样,您可以使用该find命令.我建议使用find而不是rm几乎所有情况.

既然你提到你在Linux系统上,我会在我的例子中使用GNU实现作为findutils包的一部分,因为它是大多数Linux系统的默认设置,并且我通常建议学习,因为它有更丰富和更多比许多其他实现更高级的功能集.

虽然它可能令人生畏并且看似过于复杂,但是值得花时间来掌握find命令,因为它为您提供了一种精确的表现力和安全性,在大多数其他方法中你都找不到,而基本上(很差)重新发明这个命令!

查找示例

人们经常建议find低效,容易出错和危险的方式使用命令,因此下面我概述一种安全有效的方法来完成您在示例中所要求的内容.

在删除文件之前,我建议首先预览文件列表(如果文件列表很长,则至少预览一部分列表):

find path/to/files -type f -regextype posix-extended -iregex '.*\.(avi|mkv|wmv|mp4|mp5|flv|M4V|mpeg|mov|m1v|m2v|3gp|avchd)$'
Run Code Online (Sandbox Code Playgroud)

上面的命令将显示您要删除的文件列表.要实际删除文件,您只需添加-delete动作,如下所示:

find path/to/files -type f -regextype posix-extended -iregex '.*\.(avi|mkv|wmv|mp4|mp5|flv|M4V|mpeg|mov|m1v|m2v|3gp|avchd)$' -delete
Run Code Online (Sandbox Code Playgroud)

如果你想看到什么仍将您可以通过添加反转预览比赛!的预览命令(没有-delete),像这样:

find path/to/files -type f -regextype posix-extended ! -iregex '.*\.(avi|mkv|wmv|mp4|mp5|flv|M4V|mpeg|mov|m1v|m2v|3gp|avchd)$'
Run Code Online (Sandbox Code Playgroud)

此反向匹配的输出应与执行删除后列出文件时看到的输出相同,除非由于权限问题或不可写文件系统而发生错误:

find path/to/files -type f
Run Code Online (Sandbox Code Playgroud)

说明

在这里,我将深入解释我选择的选项以及原因:

我添加-type f将匹配限制为仅文件 ; 没有它,它将匹配非文件,如您可能不想要的目录.还要注意我把它放在开头而不是结尾,因为谓词顺序对速度很重要; 与-type f第一,除非你有这将执行对仅文件,而不是针对所有的正则表达式检查......在实践中它可能没有多大意义很多目录或非文件.不过,值得记住谓词的顺序,因为它在某些情况下会产生重大影响.

我使用不区分大小写的 -iregex选项而不区分大小写的选项,-regex因为我假设您希望使用不区分大小写的匹配,因此它将包含两者.wmv .WMV文件.

为简单起见,您可能希望使用扩展POSIX正则表达式.不幸的是,还没有一个简写-regextype posix-extended,但即使我仍然建议使用它,因为你可以避免必须添加大量\反斜杠以逃避更长,更复杂的正则表达式的问题,它具有更高级(现代)的功能.GNU实现默认为emacs样式的正则表达式,如果你不熟悉它们可能会让人感到困惑.

-delete选项应该具有明显的意义,但有时人们会建议使用更慢更复杂的-exec rm {} \;选项,但通常是因为他们不知道更安全,更快速,更容易的-delete选项(在极少数情况下,您可能会遇到一个古老的系统该版本find没有此选项).知道-exec存在是有用的,但可以使用-delete它来删除文件.此外,除非您使用并理解该选项,否则不要|将输出find传递给另一个程序-print0,否则当您遇到带空格的文件时,您将陷入伤害的世界.

path/to/files我明确包含的论点.如果你把它遗漏掉它会隐含地.用作路径,但是更明智-delete地说明路径更安全(尤其是a ).

替代查找实现

即使你说你是一个Linux系统上我也将提到,你会与遇到的差异BSD实现其中包括Mac OS X的!对于其他系统(如旧的Solaris盒子),祝你好运!升级到更现代的find变种之一!

此示例的主要区别在于正则表达式.默认情况下,BSD变体使用基本的POSIX正则表达式.为了避免在Basic-PRE所需的正则表达式中额外转义繁琐,您可以通过-E使用BSD变体指定选项来利用extended-PRE的更多现代功能,以实现与使用的GNU变体相同的行为-regextype posix-extended.

find -E path/to/files -iregex '.*\.(avi|mkv|wmv|mp4|mp5|flv|M4V|mpeg|mov|m1v|m2v|3gp|avchd)$' -type f
Run Code Online (Sandbox Code Playgroud)

注意的是,这种情况下,-E选择来自之前path/to/files,而-regextype posix-extended对于GNU选项来的路径.

GNU尚未提供-E选项(但是!)太糟糕了; 因为我认为与BSD变体保持一致是一个有用的选择,我将提交补丁findutils以添加此选项,如果它被接受,我将相应地更新此答案.

rm - 不推荐

虽然我强烈建议不要使用rm,但我会举例说明如何完成或多或少地提出你的问题(有一些警告).

假设您使用带有Bourne语法的shell(通常是您在Linux系统上找到的默认为Bash shell的内容),您可以使用以下命令:

for ext in avi mkv wmv mp4 mp5 flv M4V mpeg mov m1v m2v 3gp avchd; do rm -f path/to/files/*.$ext; done
Run Code Online (Sandbox Code Playgroud)

如果你使用Bash并且启用了扩展的globbing,shopt -s extglob则可以使用模式匹配和文件名扩展:

rm -f path/to/files/*.+(avi|mkv|wmv|mp4|mp5|flv|M4V|mpeg|mov|m1v|m2v|3gp|avchd)
Run Code Online (Sandbox Code Playgroud)

+(pattern-list)扩展的通配语法将匹配给定模式的一次或多次出现.

但是,我强烈建议不要使用,rm因为:

容易出错并且很危险,因为很容易意外地在它们之间放置一个空格,*这意味着你将删除所有内容 ; 你无法提前预览命令的结果; 这是一场难以忘怀的事情,祝你好运.

它是不可移植的,因为即使它恰好在您的特定shell中工作,相同的命令行也可能在其他shell中不起作用(如果您倾向于使用Bash-isms,则包括其他Bourne-shell变体).

它有严重的限制,因为如果您有嵌套在子目录中的文件,或者甚至只有一个目录中的大量文件,那么在使用文件通配时,您将很快达到命令行长度的限制.

我希望这个rm命令能够rm被遗忘,因为我可以想到我宁愿使用的几个地方而rm不是(甚至古代的实现)find.