bash - 更新文件名中的数字

标签 bash rename mv

我有一组按数字顺序排列的文件名,如下所示:

13B12363_1B1_0.png
13B12363_1B1_1.png
13B12363_1B1_2.png
13B12363_1B1_3.png
13B12363_1B1_4.png
13B12363_1B1_5.png
13B12363_1B1_6.png
13B12363_1B1_7.png
13B12363_1B1_8.png
13B12363_1B1_9.png
13B12363_1B1_10.png
[...]
13B12363_1B1_495.png
13B12363_1B1_496.png
13B12363_1B1_497.png
13B12363_1B1_498.png
13B12363_1B1_499.png

经过一些后处理,我删除了一些文件,我想更新订购号并用新位置替换实际编号。看着这个previous question我最终做了类似的事情:

(1) ls -v |猫 -n |当读 n f 时; mv -i $f ${f%%[0-9]+.png}_$n.png;完成

但是,此命令无法识别“订购号+ png”,而只是将新编号附加在文件名末尾。类似于 13B12363_1B1_10.png_9.png

另一方面,如果我这样做:

(2) ls -v * |猫 -n |当读 n f 时;执行 mv $f ${f%.*}_$n.png;完成

添加订购号没有问题。像13B12363_1B1_10_9.png

因此,对于(1),我似乎没有正确指定digit,但我无法找到正确的语法。到目前为止,我尝试了 [0-9][0-9]+[[:digits:]][ [:数字:]]+。哪一个应该是正确的?

此外,在(2)中我想知道如何指定rename(CentOS版本)来删除第二个和第三个下划线之间的数字。在这里我不得不说我有一些文件名,例如 20B12363_22_10_9.png,所以我应该以某种方式指定第二个第三个下划线。

最佳答案

使用 Bash 的内置基本正则表达式引擎和 null 分隔的文件列表。

使用示例进行测试

#!/usr/bin/env bash

prename=$1

# Bash setting to return empty result if no match found
shopt -s nullglob

# Create a temporary directory to prevent file rename collisions
tmpdir=$(mktemp -d) || exit 1

# Add a trap to remove the temporary directory on EXIT
trap 'rmdir -- "$tmpdir"'  EXIT

# Initialize file counter
n=0

# Generate null delimited list of files
printf -- %s\\0 "${prename}_"*'.png' |

# Sort the null delimited list on 3rd field numeric order with _ separator
sort --zero-terminated --field-separator=_ --key=3n |

# Iterate the null delimited list
while IFS= read -r -d '' f; do
  
  # If Bash Regex match the file name AND
  # file has a different sequence number

  if [[ "$f" =~ (.*)_([0-9]+)\.png$ ]] && [[ ${BASH_REMATCH[2]} -ne $n ]]; then

    # Use captured Regex match group 1 to rename file with incrementing counter
    # and move it to the temporary folder to prevent rename collision with
    # existing file
    echo mv -- "$f" "$tmpdir/${BASH_REMATCH[1]}_$((n)).png"
  fi

  # Increment file counter
  n=$((n+1))
done

# Move back the renamed files in place
mv --no-clobber -- "$tmpdir/*" ./

# $tempdir removal is automatic on EXIT
# If something goes wrong, some files remain in it and it is not deleted
# so these can be dealt with manually

如果结果符合您的预期,请删除echo

示例的输出

mv -- 13B12363_1B1_495.png /tmp/tmp.O2HmbyD7d5/13B12363_1B1_11.png
mv -- 13B12363_1B1_496.png /tmp/tmp.O2HmbyD7d5/13B12363_1B1_12.png
mv -- 13B12363_1B1_497.png /tmp/tmp.O2HmbyD7d5/13B12363_1B1_13.png
mv -- 13B12363_1B1_498.png /tmp/tmp.O2HmbyD7d5/13B12363_1B1_14.png
mv -- 13B12363_1B1_499.png /tmp/tmp.O2HmbyD7d5/13B12363_1B1_15.png

关于bash - 更新文件名中的数字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64239192/

相关文章:

macos - 如何将 .txt 文件的内容写入 Mac 上的系统日志中?

linux - 查找最后一次出现的字符串并在 BASH 中打印 sed awk grep 下面的所有内容

linux - 仅当文件存在于 shell 脚本中时才移动

python - 覆盖 pytest 参数化函数名称

python - 在Python中重命名所有文件的名称

bash - 在循环中重命名匹配模式的文件 - Bash

linux - 在 Linux 中 ... 通向哪里?

Python subprocess.call bash 别名

bash : Exclude range from array

windows - 将所有文件重命名为小写,替换空格