使用“重命名”命令用零填充数字重命名文件,同时保留扩展名

使用“重命名”命令用零填充数字重命名文件,同时保留扩展名

我想用零填充数字重命名文件,同时保留扩展名。
示例
a.abc
b.cde
c.xyz

重命名为
001.abc
002.cde
003.xyz

:~/x$ rename -n -v 's/.+/our $i; sprintf("%03d.jpg", 1+$i++)/e' *
#output>
rename(a.abc, 001.jpg)
rename(b.cde, 002.jpg)
rename(c.xyz, 003.jpg)
#then
:~/x$ echo "a.abc"
a.abc
:~/x$ echo ${_##*.}
#output>
abc
so I tried>
:~/x$ rename -n -v 's/.+/our $i; sprintf("%03d.${_##*.}", 1+$i++)/' *
Global symbol "$i" requires explicit package name (did you forget to declare "my $i"?) at (user-supplied code).
Missing right curly or square bracket at (user-supplied code), within string
syntax error at (user-supplied code), at EOF

任何建议使用“改名”命令?

答案1

rename -n -v 'our $n; my $zn=sprintf("%03d", ++$n); s/[^.]*/$zn/' *

这可能会达到您的预期。而不是放置 Perl 代码里面替换,我们运行它替代。

正则表达式[^.]*将匹配任何长度的字符串,直到(但不包括)文件名中的第一个点。

为了匹配到最后的点,使用.*\.替代,并将点插入替换侧:

rename -n -v 'our $n; my $zn=sprintf("%03d", ++$n); s/.*\./$zn./' *

请注意,这也会重命名目录。


或者,使用简单的 shell 循环,假设您希望按照*shell glob 扩展文件的顺序枚举文件,并且使用bash

n=1
for filename in *; do
    [ ! -f "$filename" ] && continue
    zn=$( printf '%03d' "$n" )
    mv -i -- "$filename" "$zn.${filename##*.}"
    n=$(( n + 1 ))
done

这还会跳过任何不引用常规文件(或指向该文件的符号链接)的名称。除此之外,还有如下很接近上面的Perlrename变体,它保留一个计数器 ( n) 和计数器的零填充变体 ( zn)。

该变量n是一个简单的计数器,并且$zn具有与 相同的值$n,但作为一个用零填充的三位数。

的值$zn.${filename##*.}将扩展到零填充的数字,后跟一个点和原始文件名的最终文件名后缀。如果原始文件名中存在多个点,则直到最后的点将被零填充的数字替换。更改###替换最多第一的点。

这假设您仅对当前目录中的文件运行循环。

答案2

你可以做

rename -n -v 'our $i; s{^\./.+?(\.[^.]*)?\z}{sprintf "%03d%s", ++$i, $1}se' ./*
  • ./前缀./*:对于某些变体来说rename是必需的,否则对于以-.
  • .+?:匹配至少一个字符,因为我们不希望将前导.(对于隐藏文件,仅在dotglob启用 shell 选项时相关)被视为扩展名分隔符。
  • (\.[^.]*)?:也重命名不带扩展名的文件(如.foofoo
  • \z: 匹配主题的结尾。更一般地rename,您不想使用 ,$因为它匹配主题末尾或尾随换行符之前。
  • s标志:确保.也匹配换行符,该换行符与文件名中的任何字符一样有效。
  • eflag:替换是一个perl表达式,所以我们可以sprintf在那里使用。

相关内容