mv 改名时会做什么?

mv 改名时会做什么?

我有一个非常特殊的问题,遵循以下答案使用 Bash 脚本重命名多个文件我正在尝试重命名一些文件。这是我正在使用的代码

#!/bin/bash
for file in *.HHZ_00; do mv $file ${file/${file:14:2}/00}; done

我理解这样做的目的是将字符索引 14(从零开始)后面的 2 个字符替换为 00。

我正在使用 2 个文件子集来测试它,其中一个是这个

2018113154211.25.AGCC.HHZ_00
2018113154211.25.APAC.HHZ_00

运行代码时,这些成功重命名为

2018113154211.00.AGCC.HHZ_00
2018113154211.00.APAC.HHZ_00

第二个子集失败了,这个子集是

2018070220829.28.AGCC.HHZ_00
2018070220829.29.APAC.HHZ_00

这些未成功重命名为

2018070220829.00.AGCC.HHZ_00
2018070220800.29.APAC.HHZ_00

请注意第二个文件的索引 11 和 12 是如何更改的,而不是我想要的索引 14 和 15,非常奇怪的是,现在我第二次运行它,使用最后一个文件作为输入,我得到

2018070220829.00.AGCC.HHZ_00
2018070220800.00.APAC.HHZ_00

这是部分成功的,但现在第二个文件名被毁了......我做错了什么?是因为这些文件中的 29 重复了吗?

如果有人有使用重命名命令的解决方案,那也很棒,我尝试使用它,但我不熟悉语法。

答案1

是的,这是因为角色重复;${file/${file:14:2}/00}取代了第一的位置 14-15 中出现的任何字符的实例。

在 bash 中执行此操作的一种简单方法是,无需嵌套参数扩展

$ for file in *.HHZ_00; do 
    echo mv "$file" "${file:0:14}00${file:16}"
  done
mv 2018070220829.28.AGCC.HHZ_00 2018070220829.00.AGCC.HHZ_00
mv 2018070220829.29.APAC.HHZ_00 2018070220829.00.APAC.HHZ_00
mv 2018113154211.25.AGCC.HHZ_00 2018113154211.00.AGCC.HHZ_00
mv 2018113154211.25.APAC.HHZ_00 2018113154211.00.APAC.HHZ_00

POSIXly,您可以使用%%and #(两次)分别删除最长的后缀和最短的前缀:

$ for file in *.HHZ_00; do 
    pfx="${file%%.*}"; rem="${file#*.}"; sfx="${rem#*.}" 
    echo mv "$file" "${pfx}.00.${sfx}"
  done
mv 2018070220829.28.AGCC.HHZ_00 2018070220829.00.AGCC.HHZ_00
mv 2018070220829.29.APAC.HHZ_00 2018070220829.00.APAC.HHZ_00
mv 2018113154211.25.AGCC.HHZ_00 2018113154211.00.AGCC.HHZ_00
mv 2018113154211.25.APAC.HHZ_00 2018113154211.00.APAC.HHZ_00

echo一旦您确信它正在做正确的事情,请将其删除。

答案2

@steeldriver 解释得非常好,我通过使用纠正了这个问题

#!/bin/bash
for file in *.HHZ_00; do mv $file ${file/${file:13:4}/.00.}; done

相关内容