如何在Bash文件名中填充数字?

Tra*_*tle 46 bash rename

使用Bash重命名表单中文件的最佳方法是什么:

(foo1, foo2, ..., foo1300, ..., fooN)
Run Code Online (Sandbox Code Playgroud)

使用零填充文件名:

(foo00001, foo00002, ..., foo01300, ..., fooN)
Run Code Online (Sandbox Code Playgroud)

KAR*_*ván 60

它不是纯粹的bash,但使用rename命令更容易:

rename 's/\d+/sprintf("%05d",$&)/e' foo*
Run Code Online (Sandbox Code Playgroud)

  • 它也处理带空格的文件名。 (2认同)
  • 注意:重命名!=重命名/sf/answers/2198622051/ (2认同)

Chr*_*way 29

如果N不是先验固定:

 for f in foo[0-9]*; do mv $f `printf foo%05d ${f#foo}`; done
Run Code Online (Sandbox Code Playgroud)

  • 这会在名为 050 的文件上出现问题(例如:以零开头的数字被解释为八进制基数),输出 00040(不是预期的 00050)。见我的回答,如下。 (2认同)

Mic*_*aks 18

我有一个更复杂的案例,文件名有一个后缀和一个前缀.我还需要对文件名中的数字进行减法.

例如,我想foo56.png成为foo00000055.png.

我希望如果你做的事更复杂,这会有所帮助.

#!/bin/bash

prefix="foo"
postfix=".png"
targetDir="../newframes"
paddingLength=8

for file in ${prefix}[0-9]*${postfix}; do
  # strip the prefix off the file name
  postfile=${file#$prefix}
  # strip the postfix off the file name
  number=${postfile%$postfix}
  # subtract 1 from the resulting number
  i=$((number-1))
  # copy to a new name with padded zeros in a new folder
  cp ${file} "$targetDir"/$(printf $prefix%0${paddingLength}d$postfix $i)
done
Run Code Online (Sandbox Code Playgroud)


Fri*_*ner 9

纯 Bash,除了“mv”之外没有外部进程:

for file in foo*; do
  newnumber='00000'${file#foo}      # get number, pack with zeros
  newnumber=${newnumber:(-5)}       # the last five characters
  mv $file foo$newnumber            # rename
done
Run Code Online (Sandbox Code Playgroud)


Pio*_*ioz 5

我使用的oneline命令是这样的:

ls * | cat -n | while read i f; do mv "$f" `printf "PATTERN" "$i"`; done
Run Code Online (Sandbox Code Playgroud)

PATTERN可以是例如:

  • 使用增量计数器重命名:( %04d.${f#*.}保留原始文件扩展名)
  • 使用带前缀的增量计数器重命名:( photo_%04d.${f#*.}保留原始扩展名)
  • 使用增量计数器重命名并将扩展名更改为jpg: %04d.jpg
  • 使用带有前缀和文件basename的增量计数器重命名: photo_$(basename $f .${f#*.})_%04d.${f#*.}
  • ...

例如,您可以过滤要重命名的文件 ls *.jpg | ...

您可以使用作为f文件名的变量,i即计数器.

对于您的问题,正确的命令是:

ls * | cat -n | while read i f; do mv "$f" `printf "foo%d05" "$i"`; done
Run Code Online (Sandbox Code Playgroud)


Vic*_*art 5

在文件名中左键盘数字:

$ ls -l
total 0
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:24 010
-rw-r--r-- 1 victoria victoria 0 Mar 28 18:09 050
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:23 050.zzz
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:24 10
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:23 1.zzz

$ for f in [0-9]*.[a-z]*; do tmp=`echo $f | awk -F. '{printf "%04d.%s\n", $1, $2}'`; mv "$f" "$tmp"; done;

$ ls -l
total 0
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:23 0001.zzz
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:23 0050.zzz
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:24 010
-rw-r--r-- 1 victoria victoria 0 Mar 28 18:09 050
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:24 10
Run Code Online (Sandbox Code Playgroud)

解释

for f in [0-9]*.[a-z]*; do tmp=`echo $f | \
awk -F. '{printf "%04d.%s\n", $1, $2}'`; mv "$f" "$tmp"; done;
Run Code Online (Sandbox Code Playgroud)
  • 注意反引号: `echo ... $2}\` 反斜杠,\,正上方只是将一行行拆分为两行以提高可读性)
  • 在循环中查找以带有小写字母扩展名的数字命名的文件: [0-9]*.[a-z]*
  • 回显该文件名 ( $f) 以将其传递给awk
  • -F.:awk字段分隔符,句点 ( .):如果匹配,则将文件名分隔为两个字段 ( $1= number; $2= 扩展名)
  • 格式为printf:将第一个字段($1,数字部分)%04d打印为 4 位数字 ( ),然后打印句点,然后将第二个字段 ( $2: 扩展名)打印为字符串 ( %s)。所有这些都分配给$tmp变量
  • 最后,将源文件 ( $f)移动到新文件名 ( $tmp)