使用 bash 添加一个常量数字来移动文件名



我有一些文件名为:

0001.jpg
0002.jpg
...
0050.jpg

我需要将该数字增加 35,以便获得:

0036.jpg
0037.jpg
...
0085.jpg

我想尝试以下方法:

for i in {0001..0050}; do
mv -n $i $((i+35)) 
done

但是我收到错误bash: 0008: value too great for base (error token is "0008"). 我不确定我是否理解base在这里的含义或如何绕过它。 我见过这个问题。 虽然它解释了八进制误差,但目前还不清楚它如何帮助迭代移位索引。

最终我选择了:

for i in {50..1};
do
old=$(printf '%04d.jpg' $i)
new=$(printf '%04d.jpg' $((i + 34)))
mv -i -- "$old" "$new"  #-i to avoid overwritting
done

bash,像C一样,在算术展开中使用时,将以零开头的数字解释为八进制数。 这是 POSIX sh 的标准行为。 由于"8"不是八进制数中的有效值,因此会出现错误。

由于您想要从 1 数到 50 并加 35,然后将其格式化为数字,因此您可以执行以下操作:

#!/bin/sh
for i in $(seq 50 -1 1)
do
mv -n $(printf '%04d.jpg' $i) $(printf '%04d.jpg' $((i + 35)))
done

这将从 50 迭代到 1,并使用printf程序格式化每个数字。 顺便说一下,除了在 bash 中工作之外,这也是便携式 POSIX sh。

问题是 bash 算术将以0开头的数字视为八进制数,八进制系统中只允许 0-7 位数字。您可以在数字之前加上前缀10#以告诉 bash 接受给定的数字作为基数 10 并计算您的总和。

您可以使用:

for i in {0010..0001}.jpg; do
f="${i%.jpg}"
echo mv "$i $(printf '%04d' $((10#$f + 10#35))).jog"
done

对输出感到满意后,请在mv之前删除echo

mv 0010.jpg 0045.jog
mv 0009.jpg 0044.jog
mv 0008.jpg 0043.jog
mv 0007.jpg 0042.jog
mv 0006.jpg 0041.jog
mv 0005.jpg 0040.jog
mv 0004.jpg 0039.jog
mv 0003.jpg 0038.jog
mv 0002.jpg 0037.jog
mv 0001.jpg 0036.jog

几乎@Massagran您自己的解决方案:

#!/usr/bin/env bash
for i in {50..1}; do
printf -v old_filename '%04d.jpg' $i
printf -v new_filename '%04d.jpg' $((i + 35))
[[ -f $old_filename ]] && mv --no-clobber -- "$old_filename" "$new_filename"
done

它有何不同并改善您的答案:

  • 它不是通过在子 shell 中运行printf来捕获printf的输出到变量中,而是使用-v选项,因此printf输出直接到变量中。

  • 在执行重命名之前,它会测试旧文件名是否存在并且是实际文件。

  • 为了防止覆盖现有文件,它使用--no-clobber而不是--interactive选项。

最新更新