使用正则表达式重命名文件以删除部分名称

使用正则表达式重命名文件以删除部分名称

我有一堆文件需要在 Linux 机器上处理。这些文件看起来像这样:

2009-08-18T034353_DR1_4N-NAC_123456_1234_band1.ntf          
2009-08-18T034353_DR1_4N-NAC_123456_1234_browse.jpg    
2009-08-18T034353_DR1_4N-NAC_123456_1234_band2.ntf    
2009-08-18T034353_DR1_4N-NAC_123456_1234_license.txt    
2009-08-18T034353_DR1_4N-NAC_123456_1234_metadata.xml     
2009-08-18T034353_DR1_4N-NAC_123456_1234_readme.txt      
2009-08-18T034353_DR1_4N-NAC_123456_1234_udm.tif

我想删除这部分:-NAC_123456_1234其中第一部分可以由字母数字字符组成,数字部分只能由数字字符组成。

我尝试了重命名命令,但无法使其工作。我想到了类似的事情:

rename '/-[a-zA-Z]+_[0-9]+_[0-9]+//' *.*

有人可以帮助我解决我所缺少的吗?

我的重命名版本是:

rename from util-linux 2.23.2

答案1

您尝试使用的语法适用于 perlrename命令。根据您的操作系统,该选项可能可用或可安装为prenameperl-rename,但您需要该选项并且不是fromrename使用util-linux您正在尝试的正则表达式语法。而且,即使有了这些,你也需要一些稍微不同的东西:

perl-rename 's/-[a-zA-Z]+_[0-9]+_[0-9]+//' *.*

实际上,由于您想要的只是删除最后一个之后的所有内容-,因此您可以使用:

perl-rename 's/(.*)-(.*)(\.*)/$1$2/' *.*

不过您不需要使用这个工具。你可以运行一个小 shell 循环:

for file in *; do
    ext="${file##*.}"
    newName="${file%-*}.$ext"
    echo mv -- "$file" "$newName"
done

这只会打印将要运行的命令。如果您对它们的正确性感到满意,请删除echo并再次运行以实际重命名。

解释

  • for file in *:将迭代当前目录中的所有文件(和目录),将每个文件保存为$file.
  • ext="${file##*.}":语法从 的开头${variable##pattern}删除最长的匹配。所以在这里,这将删除直到最后一个的所有内容,留下文件的扩展名。pattern$variable.
  • newName="${file%-*}.$ext":语法从 的末尾${variable%pattern}删除 的最短匹配。所以在这里,这将把一切留给我们直到最后。然后我们添加扩展名,这给了我们新的文件名。pattern$variable-
  • mv -- "$file" "$newName": 重命名文件。

答案2

如果你有zsh,那么在那里会更容易、更安全(并且更便携)地完成:

autoload -Uz zmv
zmv -n '(*-)[[:alnum:]]##_<->_<->(*.*)' '$1$2'

-n如果满意,请删除(空运行))。

这是使用 shell glob(extendedglob启用了 zsh 的)而不是正则表达式,尽管就功能而言,您可以获得与扩展正则表达式等价的功能。

  • *通常匹配任意数量的字符(或字节,如果有字节不形成有效字符,这是它比(大多数)正则表达式更安全的原因之一
  • [[:alnum:]]是 POSIX 字符类的标准匹配。
  • ##是一个或多个先前的原子(如+ERE/PCRE 中的原子)。
  • <->是一个或多个 ASCII 十进制数字的任意序列,类似<1-10>但没有限制。

zmv在开始重命名之前将进行一些健全性检查,使其比rename周围的各种变体更安全。

相关内容