使用编号为 0 填充的名称重命名文件,同时保留预先重命名的文件



我在服务器文件夹中有几个.jpg文件,实际上大约有 20K。文件名不同,如 123.jpg、abc.jpg、ab12.jpg。需要的是使用具有前导 0 模式的 bash 脚本重命名所有这些文件。

我在下面使用了一段代码,当我每次添加新文件时,以前的文件都会再次重命名。谁能帮助我摆脱这种情况,这将非常有帮助。我已经在整个网络上搜索了这个,但没有找到一个:(

#!/bin/bash
num=0
for i in *.jpg
do
a=`printf "%05d" $num`
mv "$i" "filename_$a.jpg"
let "num = $(($num + 1))"
done

要提供该问题的具体示例,请考虑:

touch foo.jpg bar.jpg baz.jpg

首次运行此脚本时,bar.jpg重命名为filename_00000.jpg;baz.jpg更名为filename_00001.jpg;foo.jpg更名为filename_00002.jpg。此行为是可以接受的。

如果有人随后运行:

touch a.jpg

。并再次运行脚本,然后将a.jpg重命名为filename_00000.jpg,将filename_00000.jpg重命名(现在a.jpg,因为旧版本被覆盖!(重命名为filename_00001.jpg,重命名filename_00001.jpgfilename_00002.jpg,等等。

如何使程序保留已经匹配的文件filename_#####.jpg,并将新文件重命名为在已经存在的最后一个文件之后具有数字?

#!/bin/bash
shopt -s extglob  # enable extended globbing -- regex-like syntax
prefix="filename_"
# Find the largest-numbered file previously renamed
num=0                                     # initialize counter to 0
for f in "$prefix"+([[:digit:]]).jpg; do  # Iterate only over names w/ prefix/suffix
f=${f#"$prefix"}                        # strip the prefix
f=${f%.jpg}                             # strip the suffix
if (( 10#$f > num )); then              # force base-10 evaluation
num=$(( 10#$f ))
fi
done
# Second pass: Iterate over *all* names, and rename the ones that don't match the pattern
for i in *.jpg; do
[[ $i = "$prefix"+([[:digit:]]).jpg ]] && continue # Skip files already matching pattern
printf -v a '%05d' "$num"                          # More efficient than subshell use
until mv -n -- "$i" "$prefix$a.jpg"; do            # "--" forces parse of "$i" as name
[[ -e "$i" ]] || break                           # abort if source file disappeared
num=$((num + 1))                                 # if we couldn't rename, increment num
printf -v a '%05d' "$num"                        # ...and try again with the next name
done
num=$((num + 1))                                   # modern POSIX math syntax
done

请注意,使用mv -n来防止覆盖 - 这样同时运行的此脚本的两个副本就不会覆盖彼此的文件。

最新更新