希望我能解决你的问题。
如果你想用这个命令重命名多个文件以及使用一些Perl函数、代码等;您已明确声明它。因此这个命令不正确:
~ ❱ rename -n -v 's/_/printf("%.2d",$n++)/e' *.txt
Global symbol "$n" requires explicit package name (did you forget to declare "my $n"?) at (user-supplied code).
但这个是正确的:
~ ❱ rename -n -v 'my $n;s/_/printf("%.2d",$n++)/e' *.txt
00rename(0_file.txt, 01file.txt)
00rename(1_file.txt, 11file.txt)
00rename(2_file.txt, 21file.txt)
00rename(3_file.txt, 31file.txt)
00rename(4_file.txt, 41file.txt)
但这段代码的问题是printf 函数没有将其结果放入替换中,为了解决这个问题,我们可以使用sprintf。
在开头放零前导和_
~ ❱ rename -v -n 'my $n;s/^/sprintf("%.3d_",$n++)/ge' *.txt
rename(0_file.txt, 000_0_file.txt)
rename(1_file.txt, 000_1_file.txt)
rename(2_file.txt, 000_2_file.txt)
rename(3_file.txt, 000_3_file.txt)
rename(4_file.txt, 000_4_file.txt)
正如您所见,所有000_ 都为零,因为$n 是本地的,并且它是按行声明的。
因此我们可以通过:our 关键字这样的全局化:
~ ❱ rename -v -n 'our $n; s/^/sprintf("%.3d_",$n++)/ge' *.txt
rename(0_file.txt, 000_0_file.txt)
rename(1_file.txt, 001_1_file.txt)
rename(2_file.txt, 002_2_file.txt)
rename(3_file.txt, 003_3_file.txt)
rename(4_file.txt, 004_4_file.txt)
最终您的要求:我想从 title223 重命名
我不确定,但我认为你不能以这种方式使用rename 命令,它应该可以工作但是......!!!
在这种情况下,我更喜欢使用 Perl one-liner
使用 Perl 非递归版本重命名:
~ ❱ perl -le '($old=$_) && s/^/sprintf("%.3d_",$n++)/e && print "$old => $_" for <*.txt>'
0_file.txt => 000_0_file.txt
1_file.txt => 001_1_file.txt
2_file.txt => 002_2_file.txt
3_file.txt => 003_3_file.txt
4_file.txt => 004_4_file.txt
并且对于开始形成一个特殊的值,例如223:
~ ❱ perl -le '$n=223; ($old=$_) && s/^/sprintf("%.3d_",$n++)/e && print "$old => $_" for <*.txt>'
0_file.txt => 223_0_file.txt
1_file.txt => 224_1_file.txt
2_file.txt => 225_2_file.txt
3_file.txt => 226_3_file.txt
4_file.txt => 227_4_file.txt
使用rename $old,$_ 函数代替print "$old => $_。
使用 Perl 递归版本重命名:
对于这个你必须使用find 命令
~ ❱ find . -name '*.txt'
./4_file.txt
./2_file.txt
./0_file.txt
./3_file.txt
./1_file.txt
~ ❱ find . -name '*.txt' > find.log
~ ❱
~ ❱ # run perl with print just for test
~ ❱
~ ❱ perl -lne '$n=223; ($old=$_) && s/(?<=\.\/)(?=)/sprintf("%.3d_",$n++)/e && print "$old => $_"' find.log
./4_file.txt => ./223_4_file.txt
./2_file.txt => ./223_2_file.txt
./0_file.txt => ./223_0_file.txt
./3_file.txt => ./223_3_file.txt
./1_file.txt => ./223_1_file.txt
~ ❱
~ ❱ # Ohhhhh Nooooo it is still 233!
~ ❱
~ ❱ # first solution: using BEGIN{ $n=233 }
~ ❱
~ ❱ perl -lne 'BEGIN{$n=223}; ($old=$_) && s/(?<=\.\/)(?=)/sprintf("%.3d_",$n++)/e && print "$old => $_"' find.log
./4_file.txt => ./223_4_file.txt
./2_file.txt => ./224_2_file.txt
./0_file.txt => ./225_0_file.txt
./3_file.txt => ./226_3_file.txt
./1_file.txt => ./227_1_file.txt
~ ❱
~ ❱ # second solution is: using static declaration
~ ❱ # in Perl it is: state
~ ❱ # thus we should use: state $n=223;
~ ❱ # but we have to turn on Perl 5 feature with -E
~ ❱
~ ❱ perl -lnE 'state $n=233; ($old=$_) && s/(?<=\.\/)(?=)/sprintf("%.3d_",$n++)/e && print "$old => $_"' find.log
./4_file.txt => ./233_4_file.txt
./2_file.txt => ./234_2_file.txt
./0_file.txt => ./235_0_file.txt
./3_file.txt => ./236_3_file.txt
./1_file.txt => ./237_1_file.txt
~ ❱
~ ❱ # test it with rename $old,$_
~ ❱ perl -lnE 'state $n=233; ($old=$_) && s/(?<=\.\/)(?=)/sprintf("%.3d_",$n++)/e && rename $old,$_' find.log
~ ❱
~ ❱ # see the result:
~ ❱
~ ❱ ls *.txt | cat -n
1 233_4_file.txt
2 234_2_file.txt
3 235_0_file.txt
4 236_3_file.txt
5 237_1_file.txt
注意 BEGIN{} 和 state 不适用于 rename 命令。为什么?我不知道:)