如何使用“查找”通过正则表达式搜索文件名并重命名此文件

如何使用“查找”通过正则表达式搜索文件名并重命名此文件

我试图找到所有以以下结尾的文件:

  • 祖先-人类-奥德赛-预告片-720-1262.mp4
  • 高科技潜水员-1080-1234.mp4
  • 亚马逊潜水员-720-1323.mp4

并像这样重命名该文件:

  • 720-1262.mp4
  • 1080-1234.mp4
  • 720-1323.mp4

我使用正则表达式但什么也没用,为什么?请问怎么了?

find . -regex '^.*-(([0-9])*-([0-9])*)\.mp4'

只有一个目录和这些文件,没有子目录。大约 300 个 .mp4 文件

答案1

GNUfind支持多种正则表达式方言(该-regextype选项允许您选择一种)。括号在其中一些字符中是特殊字符,需要进行反斜杠转义才能在其他字符中获得特殊含义。

根据在线文档,使用的默认方言-regex是“POSIX basic”,而手册页网上说默认方言是“Emacs” 1。在这两个括号中,括号都需要进行反斜杠转义才能用作分组字符。

这些会起作用:

find . -regex '^.*-\(\([0-9]\)*-\([0-9]\)*\)\.mp4'
find . -regextype posix-extended -regex '^.*-(([0-9])*-([0-9])*)\.mp4'

然而,^这里不需要(-regex对文件名执行完全匹配)并且分组似乎没有必要;因此

find . -regex '.*-[0-9]*-[0-9]*\.mp4'

应该足够了(抛开与排序规则相关的潜在问题:[0-9]可以匹配比 更多的东西[0123456789],具体取决于您的区域设置)。

关于重命名: 的 Perl 实现rename(如果您可以使用)将是一个方便的选择。假设所有要重命名的文件都在当前工作目录中(不需要find):

perl-rename -nv 's/.*-(\d*-\d*\.mp4)\Z/$1/' -- *

(其中\Z相当于主题2$末尾匹配的标准正则表达式)。

n当您对命令的作用感到满意时,请删除(空运行)选项。

注意

  • 这也将重命名--.mp4-.mp4:用于\d+要求在最后一个数字之前和之后至少出现一个数字-
  • .*还需要重命名隐藏文件

或者,使用 GNUfind和标准mv实用程序(也递归地下降到子目录):

find . -regex '.*-[0-9]*-[0-9]*\.mp4' -execdir sh -c '
  for file; do
    toremove=${file%-*-*.mp4}
    echo mv -- "$file" "${file#"$toremove"-}"
  done' mysh {} +

echo当您对该命令的作用感到满意时,请删除。


¹ 作为斯蒂芬·查泽拉斯在评论中指出,已经在 savannah.org 上提交了一些关于文档中的不准确/不一致的错误报告:https://savannah.gnu.org/bugs/?58384,https://savannah.gnu.org/bugs/?52592,https://savannah.gnu.org/bugs/?61304
² Perl 的$匹配位于主题末尾,而且也在主题末尾的换行符之前,因此,虽然在处理可能包含或不包含分隔符的文本行时很好,但\Z在处理其他任何内容(例如文件名在这里。

答案2

zsh

autoload zmv
zmv -n '(**/)*-(<->-<->.mp4)' '$1$2'

-n如果愿意,请删除以进行空运行)。

相关内容