如何在使用批量重命名设置序列编号时设置初始值?
在这个回答中,使用了以下命令:
1
|
rename -n 'our $i; s/_.*/sprintf("_%03d.png", $i++)/e' *.png
|
将文件从:
1
2
3
4
|
abc_128390.png
abc_138493.png
abc_159084.png
...
|
重命名为:
1
2
3
4
|
abc_001.png
abc_002.png
abc_003.png
...
|
我需要做完全相同的事情,但从28开始编号:
1
2
3
4
|
abc_028.png
abc_029.png
abc_030.png
...
|
但是当我改为:
1
|
rename -n 'our $i = 28; s/_.*/sprintf("_%03d.png", $i++)/e' *.png
|
它返回:
1
2
3
4
|
rename(abc_128390.png, abc_028.png)
rename(abc_138493.png, abc_028.png)
rename(abc_159084.png, abc_028.png)
...
|
所有文件都获得相同的名称。
为什么这次编号没有增加?
如何正确修改上述命令以实现我的需求?
解决方案
方法一:使用BEGIN块
将our $i = 28;放在主脚本中不起作用,因为它会为每个文件名将$i重置为28 - rename对每个文件名执行一次主脚本中的每个语句。
您可以在BEGIN块中为变量设置初始值(或任何其他只需要在脚本首次执行时运行一次的设置代码)- 例如BEGIN {our $i = 28};。
您仍然需要在BEGIN块和主脚本中使用our将变量声明为包全局变量,因为rename在严格模式下运行perl代码。
1
2
3
4
5
6
|
$ rename -n 'BEGIN {our $i = 28};
our $i;
s/_.*/sprintf("_%03d.png", $i++)/e' *.png
rename(abc_128390.png, abc_028.png)
rename(abc_138493.png, abc_029.png)
rename(abc_159084.png, abc_030.png)
|
注意:您不必每次使用变量时都用our声明它。在每个代码块中只声明一次,即在BEGIN中一次,在主脚本中一次 - 要么在代码块中首次使用之前,要么在块中首次使用时。这也有效:
1
2
|
$ rename -n 'BEGIN {our $i = 28};
s/_.*/sprintf("_%03d.png", our $i++)/e' *.png
|
方法二:使用defined-or运算符
一个简单的方法是:
这仍然将其声明为包全局变量以绕过strict,但仅在尚未定义时才分配28。
方法三:使用state变量
将$i声明为state变量也可以,不需要BEGIN块,但建议避免使用,除非您对perl中的变量作用域有很好的理解:
1
2
3
4
5
|
$ rename -n 'state $i = 28;
s/_.*/sprintf("_%03d.png", $i++)/e' *.png
rename(abc_128390.png, abc_028.png)
rename(abc_138493.png, abc_029.png)
rename(abc_159084.png, abc_030.png)
|
方法四:使用Perl主内部变量
这是使用Perl主内部变量的一种方法,不需要使用our全局变量:
1
|
rename -n 'BEGIN{$main::i = 28} s/_.*/sprintf("_%03d.png", $main::i++)/e' ./*.png
|
这里的解决方案是使用完全限定的标量变量$main::i(与在main包中时相同)。
方法五:使用zsh的zmv
使用zsh的zmv:
1
2
|
autoload -Uz
n=28; zmv -n '(*_)<->(.png)' '$1${(l[3][0])$((n++))}'
|
(与大多数rename实现一样,-n用于试运行)。