重命名具有编号0填充名称的文件,同时单独保留预重命名的文件

时间:2018-05-30 04:50:44

标签: bash

我在几个文件夹中有几个.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匹配的文件,并将新文件重命名为最后一个已存在的数字?

1 个答案:

答案 0 :(得分:1)

#!/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来防止覆盖 - 这样,同时运行此脚本的两个副本不会覆盖彼此'文件。