尝试在 Perl 重命名工具(Debian)中进行算术运算

尝试在 Perl 重命名工具(Debian)中进行算术运算

假设我有五个 mp3 文件:

01-trackfoo.mp3
02-trackbar.mp3
03-trackbaz.mp3
04-trackabc.mp3
05-trackxyz.mp3

现在我快速听一下这些文件(只需控制台上的 mplayer 就可以了),我发现曲目位于错误的顺序。 05实际上是02,其余的必须重命名。所以首先我将进行临时重命名:

01-trackfoo.mp3

02-trackbar.mp3
03-trackbaz.mp3
04-trackabc.mp3
00-trackxyz.mp3

现在我们需要一个“转变”:02 应该变成 03,03 应该变成 04,04 应该变成 05。为了尽量减少混乱,ex-05(现在是 00)稍后会被mv编辑。

我的方法是这样的:(perl rename,作者 Larry Wall,Debian 上默认)

rename 's/0([2-4])([\s\S]+)/0($1+1)$2/' *

以及(稍后,经过更多的 RTFM'ing)

rename 's/0([2-4])([\s\S]+)/0($1+1)$2/e' *

它们都不起作用,特别是因为/e[val]修饰符不接受其他任何内容评估,并且一旦您尝试将评估与字符串组合起来就会抛出错误。可以bash做得很好,例如 foo$((1+6))将被评估为foo7

那么我该如何做到这一点(首选单行,不打算为此编写一个完整的独立脚本)?

答案1

你几乎已经拥有了。您只需要/e使用引号和点运算符在 -modified 替换中显式地显示文字字符串和字符串连接。

rename 's/0([2-4])([\s\S]+)/"0".($1+1).$2/e' *

答案2

首选单行脚本,不打算为此编写一个完整的独立脚本

当事情变得如此复杂时,我看不出有什么理由不写脚本。您永远不会记住如何从一次运行到下一次运行,因此您最终要么每次都重新发明它,要么将其包装在脚本中。

对于像这样的小事情,我通常会开始尝试在 Bash 中解决它:

#!/bin/bash
if [ -z "$1" ] ; then echo Need arguments. ; exit 1 ; fi

typeset -i i=1
for f in "$*"
do
    tailbits=`echo "$f" | sed -e 's/^[0-9]+//'`
    mv "$f" sertmp-`printf %02d $i`"$tailbits"
    i=i+1
done

for f in "sertmp-*"
do
    mv "$f" `echo "$f" | sed -e s/^sertmp-//` 
done

基本上,该脚本会去掉所有前导数字,然后在前面放置一个以零填充的递增序列号,文件根据您传递给脚本的顺序进行编号。

它分两个阶段执行此操作,sertmp-第一遍使用前缀以避免任何名称冲突的风险。如果您调用此脚本mp3-renamer并像这样调用它:

$ mp3-renamer 01-foo.mp3 03-bar.mp3 04-qux.mp3

如果您不使用 2 遍进行重命名,则在第一次重命名时会遇到轻微的冲突。 ( 01-foo.mp3-> 01-foo.mp3。)

但如果你这样称呼它:

$ mp3-renamer 02-foo.mp3 01-foo.mp3

01-foo.mp3在第一次重命名时不小心删除了一次重命名。

如果问题变得更复杂,我会用 Perl 重写它。此时,您可以使用散列来保存旧名称到新名称的映射,并使用一些巧妙的代码来计算出进行重命名的正确顺序,以避免需要两次传递。

相关内容