如何删除文件名中没有给定字符串的特定扩展名的文件?

如何删除文件名中没有给定字符串的特定扩展名的文件?

我有一个目录,里面有许多扩展名的文件。我想递归删除*.srt以下文件(*.srt仅限文件):不要结束使用-en.srt(其中srt是扩展名)。我想出了以下解决方案,它似乎工作正常,但是,我想知道它是否 100% 正确。

find . -name "*.srt" ! -name "*-en.srt" -type f -exec rm -rf {} \;

答案1

!——首先完整阅读答案,然后如果喜欢的话就使用它——!

您的命令是正确的,但是不需要使用-rf参数rm。因为您要删除文件而不是目录。

另一种清晰的写法是(它几乎与您的命令相同):

find -name '*.srt' -and -not -name '*-en.srt' -type f -exec rm '{}' \;

或者按照@steeldriver 建议的你可以使用:

find -name '*.srt' -and -not -name '*-en.srt' -type f -ok rm '{}' \;

它将请求您的许可来删除每个建立的文件。

您也可以使用它-delete,但rm {} \;要注意它的危险:

不要忘记 find 命令行被评估为一个表达式,因此将 -delete 放在首位将使 find 尝试删除您指定的起始点以下的所有内容。在测试您稍后打算与 -delete 一起使用的 find 命令行时,您应该明确指定 -depth 以避免以后出现意外。由于 -delete 隐含 -depth,因此您不能同时使用 -prune 和 -delete。


在进行实际工作之前测试一下会发生什么总是一个好主意,因此我建议运行:

find -name '*.srt' -and -not -name '*-en.srt' -type f | grep -i en.srt

如果它什么都不返回,那么实际的命令将毫无问题地工作并且你就可以继续...甚至:

find -name '*.srt' -and -not -name '*-en.srt' -type f | less

检查将要删除的内容。

并且不要忘记引用'{}'

(当从 shell 调用 find 时)应该将其引起来(例如,'{}')以防止它被 shell 解释。

答案2

让我们仅使用bash通配符来实现这一点:启用extglobglobstar选项后,

rm **/!(*-en).srt

删除所有以 结尾的文件,不包括当前目录和子目录.srt中以 结尾的任何文件。 如果您不确定这样的扩展,请通过添加前缀进行测试(参见下面的示例)。-en.srt
echo

例子

$ tree
.
├── 01.srt
├── 02.srt
├── no-en.srt
├── not-en.srt
├── subdir
│   ├── 01.srt
│   ├── 02.srt
│   ├── no-en.srt
│   └── not-en.srt
└── unrelated.png
$ shopt -s extglob globstar
$ echo rm **/!(*-en).srt
rm 01.srt 02.srt subdir/01.srt subdir/02.srt
$ rm **/!(*-en).srt
$ tree
.
├── no-en.srt
├── not-en.srt
├── subdir
│   ├── no-en.srt
│   └── not-en.srt
└── unrelated.png

解释

  • **/globstar启用该选项后,将匹配任意数量的目录和子目录
  • !(*-en)extglob启用该选项后,它将匹配除给定模式之外的任何内容,因此任何不以-en

相关内容