我在服务器文件夹中有几个.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.jpg
filename_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
来防止覆盖 - 这样同时运行的此脚本的两个副本就不会覆盖彼此的文件。