假设我有五个 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 重写它。此时,您可以使用散列来保存旧名称到新名称的映射,并使用一些巧妙的代码来计算出进行重命名的正确顺序,以避免需要两次传递。