我的文件有以下模式:
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
此外,我还试图找到命令,这会将名称的其余部分设置为正确,但我无法找到它。有人知道吗,或者知道如何做到这一点?
答案 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'