如何使用终端批量重命名一组多个数字共享相同前缀的文件,以便将所有这些前缀设置为新的?
例如:
011.foo.txt -> 001.foo.txt
011.bar.psd -> 001.bar.psd
011.baz.gif -> 001.baz.gif
012.qux.js -> 002.qux.js
012.corge.png -> 002.corge.png
...
020.thud.txt -> 010.thud.txt
如果可能的话,我想使用重命名命令:
rename [ -h|-m|-V ] [ -v ] [ -0 ] [ -n ] [ -f ] [ -d ] [ -e|-E perlexpr]*|perlexpr [ files ]
非常感谢您帮助解决这个问题,谢谢!
答案1
使用 perlrename
按照要求。
从你提出的问题可以看出:
rename -n 's/^(\d+)/sprintf "%03d", $1-10/e' *
空运行输出:
rename(011.bar.psd, 001.bar.psd)
rename(011.baz.gif, 001.baz.gif)
rename(011.foo.txt, 001.foo.txt)
rename(012.corge.png, 002.corge.png)
rename(012.qux.js, 002.qux.js)
rename(020.thud.txt, 010.thud.txt)
对于问题标题所说的内容,带有实际的顺序前缀:
rename -n -E 'use vars q{$n}' -e 's/^(\d+)/sprintf "%03d", ++$n/e' *
rename(011.bar.psd, 001.bar.psd)
rename(011.baz.gif, 002.baz.gif)
rename(011.foo.txt, 003.foo.txt)
rename(012.corge.png, 004.corge.png)
rename(012.qux.js, 005.qux.js)
rename(020.thud.txt, 006.thud.txt)
对于第一个,如果你不想对增量进行硬编码10
:
rename -n -E 'use vars q{$delta}' -e '
s{^(\d+)}{
$delta = $1 - 1 unless defined $delta;
sprintf "%03d", $1 - $delta
}e
' *
答案2
如果希望具有相同原始前缀的文件在新方案中映射到相同的前缀没有依靠减法,那么您可以通过创建前缀的哈希(关联数组)来实现,按顺序对其进行编号,然后通过在哈希中查找来执行重命名替换。例如
$ rename -n -E '
BEGIN {
my $n = 1;
our %pfxs;
foreach my $f (@ARGV) {
$pfxs{$1} = (exists $pfxs{$1} ? $pfxs{$1} : $n++) if $f =~ /^(\d{3})/
}
}
our %pfxs;
s/^(\d{3})/sprintf "%03d", $pfxs{$1}/e
' [0-9][0-9][0-9].*
rename(011.bar.psd, 001.bar.psd)
rename(011.baz.gif, 001.baz.gif)
rename(011.foo.txt, 001.foo.txt)
rename(012.corge.png, 002.corge.png)
rename(012.qux.js, 002.qux.js)
rename(020.thud.txt, 003.thud.txt)
由于它不依赖于减法,因此即使原始前缀是非数字的也可以使用此方法。
$n
这无疑可以得到改进——特别是,可以检查映射末尾的最大值并据此选择输出的宽度。
答案3
在 bash 中
在包含文件的目录中尝试此操作(试运行):
for f in *
do
r="${f#*.}"
p="${f%%.*}"
if [ "$p" -eq "$p" ] 2>/dev/null
then
p="$((10#$p - 10))"
p="$(printf "%03d" $p)"
echo mv -- "$f" "$p.$r"
fi
done
如果您对打印的输出满意,则将以下行更改:
echo mv -- "$f" "$p.$r"
到:
mv -- "$f" "$p.$r"
删除echo
以进行实际的重命名。