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


8

假设我有五个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。为了最大程度地减少混乱,将mv稍后编辑ex-05(现在为00)。

我的方法是这样的:(perl rename,由Larry Wall提供,默认为Debian)

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

以及(之后再进行一些RTFM操作)

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

它们都/e[val]不起作用,特别是因为修饰符除了求值以外不接受其他任何东西,并且一旦您尝试将求值与字符串结合起来就会抛出错误。该bash能做到这一点就好了,例如, foo$((1+6))将被评估到foo7

那么,我该怎么做(首选单行代码,不打算为此编写整个独立脚本)?

Answers:


7

你差点就吃了。您只需要/e使用引号和点运算符在-modified替换中使文字字符串和字符串连接显式。

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

它让原来的05仍然未改名,但+1解决的一个班轮毛刺。
Peter.O 2012年

1
(小记,重命名被称为女士prename在Ubuntu)...如果在目录开始没有名字有$'\x01'2那么这样一个初步的重命名:prename 's/^05/\x012/' 05*..然后上面的[2-4]命名..然后最终prename 's/^\x01/0/' $'\x01'2*会做的伎俩..这使得3一个-liners ...对于第四个文件,以及对文件开头是否可能存在的初始检查$'\x01',像这样的bash片段都会将其捕获..shopt -s nullglob; x=($'\x01'*); [[ -n $x ]] && { echo '\x01' is not suitable; exit; }
Peter.O 2012年

耶!谢谢艾伦,我没想到那个点运算符,尽管我确实知道用人类可以理解的单词做什么:“告诉/ e不要碰()之外的东西” :)还要感谢彼得的热情方法。此外,如果我对PHP语法与Perl的接近程度有所了解,我可能会通过反复试验找到解决方案。因为该点是PHP中用于字符串连接的JavaScript'+'对应物。
syntaxerror

4

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

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

对于这样的小事情,我通常开始尝试在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用1遍重命名删除了第一个重命名。

如果问题变得更加复杂,我将在Perl中重写它。那时,您可以使用散列来保存旧名称到新名称的映射,并使用一些巧妙的代码来确定重命名的正确顺序,以避免需要两次通过。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.