使用shell重命名文件名中的编号

时间:2014-12-08 14:57:02

标签: bash shell

我的文件有以下模式:

a0015_random_name.txt
a0016_some_completely_different_name.txt
a0017_and_so_on.txt
...

我想只使用shell重命名编号,这样他们就会向下移两个数字:

a0015_random_name.txt ---> a0013_random_name.txt
a0016_some_completely_different_name.txt ---> a0014_some_completely_different_name.txt
a0017_and_so_on.txt ---> a0015_and_so_on.txt

我已经尝试过这个:

let n=15; for i in *.txt; do let n=n-2; b=`printf a00`$n'*'.txt; echo "mv $i $b"; done

(我首先使用echo,以便了解会发生什么)

但这给了我:

mv a0015_random_name.txt a0013*.txt
mv a0016_some_completely_different_name.txt a0014*.txt
mv a0017_and_so_on.txt a0015*.txt

此外,我还试图找到命令,这会将名称的其余部分设置为正确,但我无法找到它。有人知道吗,或者知道如何做到这一点?

2 个答案:

答案 0 :(得分:4)

您的代码几乎是正确的。试试这个:

let n=15; for i in *.txt; do let n=n-2; b=`echo $i | sed "s/a[0-9]*/a$n/g`; echo "mv $i $b"; done

更好的是,为了使其更强大,请使用以下修改:

let n=15; for i in *.txt; do let t=n-2; let n=n+1; b=`echo $i | sed "s/a00$n/a00$t/g`; echo "mv $i $b"; done

答案 1 :(得分:2)

如果你有Perl rename.pl脚本,这是一个单行:

rename 's/\d+/sprintf "%0${\(length $&)}d", $&-2/e' *.txt

否则,它有点啰嗦。这是一种方式:

for f in *.txt; do
  number=$(expr "$f" : '^[^0-9]*\([0-9]*\)') # extract the first number from the filename
  prefix=${f%%$number*}                      # remember the part before 
  suffix=${f#*$number}                       # and after the number
  let n=10#$number-2                         # subtract 2
  nf=$(printf "%s%0${#number}d%s" \
              "$prefix" "$n" "$suffix")      # build new filename
  echo "mv '$f' '$nf'"                       # echo the rename command
  # mv "$f" "$nf"                            # uncomment to actually do the rename
done

注意10#行上的let - 强制数字在基数10中被解释,即使它具有前导零,否则会导致它在基数8中被解释。此外, %0${#number}d格式告诉printf使用足够的前导零格式化新数字,使其与原始数字的长度相同。

在您的示例中,上面的脚本生成此输出:

mv 'a0015_random_name.txt' 'a0013_random_name.txt' 
mv 'a0016_some_completely_different_name.txt' 'a0014_some_completely_different_name.txt' 
mv 'a0017_and_so_on.txt' 'a0015_and_so_on.txt'