使用不同的填充批量重命名文件名中的多个数字



我正在尝试重命名以下形式的一批文件:

test1_run1
test1_run2
   ...
test1_run10
  ...
test10_run1
test10_run2
  ...
test10_run10

到具有多个填充的窗体。对于第一个数字,我需要用长度为 5 的零填充,对于第二个长度为 3 的数字,我需要填充。

最终结果应为以下形式:

test00001_run001
test00001_run002
  ...
test00001_run010
  ...
test00010_run001
test00010_run002
  ...
test00010_run010

如何在 bash 中对特定文件夹中的所有文件执行此操作?

我们可以将字符串转换为 test + 5 digits + _run + 3 digits 格式,方法是说:

$ awk -F"test" '{split($2,a,"_run"); printf "%s%0.5d%s%0.3dn", FS, a[1], "_run", a[2]}' a
test00001_run001
test00001_run002
test00001_run010
test00010_run001
test00010_run002
test00010_run010

这是通过使用test作为字段分隔符并将第二个字段分为两部分来工作的:_run之前和之后。然后,它使用printf的东西来获得正确的输出。

然后,您可以将mv与以前的值一起打印并说:

$ awk -F"test" '{split($2,a,"_run"); printf "mv %s %s%0.5d%s%0.3dn", $0, FS, a[1], "_run", a[2]}' a
mv test1_run1 test00001_run001
mv test1_run2 test00001_run002
mv test1_run10 test00001_run010
mv test10_run1 test00010_run001
mv test10_run2 test00010_run002
mv test10_run10 test00010_run010

如果你然后用管道将它传送到 sh ,它将被执行。

如果你不想使用 perl 或 awk,并且严格使用 bash 和大多数发行版中可用的一些实用程序,你可以尝试这样的事情:

for i in * ; do
    testpart=`echo $i | cut -d_ -f1`
    testnum=${testpart#test}
    runpart=`echo $i | cut -d_ -f2`
    runnum=${runpart#run}
    destfile=test`printf %05d $testnum`_run`printf %03d $runnum`
    mv $i $destfile
done

In bash:

#!/bin/bash
shopt -s nullglob extglob
for file in test+([[:digit:]])_run+([[:digit:]]); do
    [[ $file =~ ^test([[:digit:]]+)_run([[:digit:]]+)$ ]]
    printf -v newfile 'test_%05d_run%03d' "$((10#${BASH_REMATCH[1]}))" "$((10#${BASH_REMATCH[2]}))"
    echo mv "$file" "$newfile"
done

从要处理的文件夹中运行此命令。这将仅echo要执行的mv命令。如果您对结果感到满意,请删除echo

  • 我们使用 shell 选项nullglob,以便不匹配的 glob 扩展到无;
  • 我们extglob使用 shell 选项,因为 for 循环将使用扩展的 glob;
  • 扩展的 glob test+([[:digit:]])_run+([[:digit:]])将扩展到与此模式匹配的文件(如果有(
  • 我们使用正则表达式从文件名中获取数字;第一个数字将以BASH_REMATCH[1]为单位,第二个数字为BASH_REMATCH[2]
  • 我们使用printf来格式化新文件名;修饰符%05d%03d将根据您的意愿格式化数字(使用适当的前导零(。请注意,我们使用 ((10#${BASH_REMATCH[1]})) 来显式指定数字以基数 10 为单位,以防您有一个文件test09_run00109部分会使 bash 误解基数 8 中的数字(因为前导 0(,你会得到投诉;-v开关告诉printf不要在标准输出上输出,而是将输出存储在可变newfile中;
  • 最后我们执行mv

最新更新