Bash:用分隔符分割的子字符串减一

Bash:用分隔符分割的子字符串减一

我想批量重命名文件名 A-B-C#2-D.wav转向A-B-C#1-D.wav.例如:

A-B-C#2-D.wav
A-B-C#8-G.wav
A-B-C6-E.wav

变成

A-B-C#1-D.wav
A-B-C#7-G.wav
A-B-C5-E.wav

所以第三个子串中的数字应该减一。 (#是文件名的一部分,而不是注释;带或不带文件名#都是可能的。)

答案1

zsh

autoload zmv # best in ~/.zshrc
zmv -n '(*[^0-9])(<1->)(*.wav)(#qn)' '$1$(($2-1))$3'

(如果满意则删除-n

用于(#qn)对列表进行数字排序以便A-B-C#9-D.wav重命名 A-B-C#10-D.wav例如。

但是,如果同时存在 aA-B-C#9-D.wavA-B-C#10-D.wav,zmv将标记一个文件将被重命名为现有文件的名称并中止该命令。您需要添加-f选项才能仍然强制执行它。

或者使用 zsh (对于数字全局顺序)和perl's 重命名:

rename -n 's/\d+/$&-1/e' ./*[1-9]*.wav(#qn)

-f(与某些变体相同的警告和相同的选项rename)。

答案2

使用特定于 bash 的循环(用于正则表达式测试条件=~):

for file in ?-?-*-?.wav
do
  [[ $file =~ ^([^[:digit:]]+)([[:digit:]]+)(-.\.wav)$ ]] &&
    echo mv -- "$file" "${BASH_REMATCH[1]}$((10#${BASH_REMATCH[2]} - 1))${BASH_REMATCH[3]}"
done

这使用通配符来选取所需的wav文件;匹配的文件将在破折号之间和.wav末尾之前有一个字符(字母)。每个文件名都通过正则表达式运行,将其分为三部分:

  1. ^([^[:digit:]]+)——引导部分;一切直到但不包括第一个数字
  2. ([[:digit:]]+)-- 数字
  3. (-.\.wav)-- 尾随部分

如果匹配成功,则我们使用前导部分、数字减一和尾随部分重命名该文件。

echo当输出看起来正确时删除。

相关内容