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

时间:2015-02-13 11:28:26

标签: bash shell file-rename batch-rename renaming

我正在尝试重命名一批格式的文件:

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

到具有多个填充的表单。对于第一个数字,我需要填充长度为零的零,而第二个长度为3。

最终结果应采用以下形式:

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

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

3 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:1)

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

$ awk -F"test" '{split($2,a,"_run"); printf "%s%0.5d%s%0.3d\n", 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.3d\n", $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,它将被执行。

答案 2 :(得分:1)

如果您不想使用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