我有几个名称不正确的文件:
$ ls
devoirNote1_1_2.R devoirNote1_1_5.R devoirNote1_4_1.R
devoirNote1_1_3.R devoirNote1_1.R devoirNote1.R
devoirNote1_1_4.R devoirNote1_2_1.R example140.R
我想devoirNote1_i_j.R
用 i 和 j 整数更改除devoirNote1_4_1.R
to之外的所有内容devoirNote1_{i+1}_j.R
(仅devoirNote1_4_1.R
保持不变)。
我想过使用mv
类似的命令mv devoirNote1_*_2.R devoirNote1_2_2.R
,但是当多个文件匹配时(例如,如果 和devoirNote1_1_2.R
都devoirNote1_3_2.R
存在),它会产生一个问题。
因此,如何创建一个脚本或命令行来重命名我的文件,通过增加文件名中的变量之一而不是全部变量?
答案1
Perl 的rename
实用程序(*)可用于此目的。它将给定的 Perl 命令应用于每个给定的文件名,并将文件重命名为命令将名称更改为的任何名称。
因此,这将更改为_1_
glob_2_
匹配的所有文件。
rename 's/_1_/_2_/' devoirNote1_*_2.R
可以通过/e
修改替换命令来完成数字递增,使替换部分成为 Perl 片段而不是文字。
rename -v 's/_(\d+)_/"_" . ($1 + 1) . "_"/e' devoirNote1_*_2.R
这将选择文件名中下划线之间包含数字的部分,将数字捕获到$1
,并将其替换为增加的数字,并将下划线添加回来。-v
对于详细模式。使用示例中的文件列表,这将按devoirNote1_1_2.R renamed as devoirNote1_2_2.R
预期打印。
受影响的文件是命令行末尾的 glob 匹配的文件。
但请注意,如果您有,例如1_1_2
和1_2_2
,则重命名第一个将会失败,因为它会与下一个发生冲突。这需要以相反的顺序给出文件名,或者先将它们更改为某种不冲突的形式,然后再更改回来,例如通过添加额外的字符。
答案2
一个脚本对于两次(批量)移动来说是多余的。使用该mmv
实用程序:
mmv devoirNote1_2_"*" devoirNote1_3_#1
mmv devoirNote1_1_"*" devoirNote1_2_#1
当然按照这个顺序。如果有两个以上的动作,那么脚本确实会更好。
答案3
在这里,我们使用过滤器从搜索列表中negative lookaheads
过滤出文件。*Note1_3_2.R
*Note1_4_2.R
OP 想要保持*Note1_4_2.R
原样=>我们也不能碰之前的一个文件,即 ,*Note1_3_2.R
因为我们没有地方可以 mv 这个。
循环for
逻辑对 1 和 2 之间的索引号执行 a ,reverse numeric sort
以便我们可以执行非破坏性的 mv 操作。
perl -e '
/(.*)_(\d+)_(.*)/ and
rename $_, join "_", $1, $2+1, $3 or warn "Could not mv the file <<$_>>\n"
for
map { $_->[0] }
sort { $b->[2] <=> $a->[2] || $b->[1] <=> $a->[1] }
map { [$_, /_(\d+)_(\d+)/] }
grep { /^devoirNote1_(?![34]_1.R)\d+_\d+.R/ }
<*.R>
'