更改文件名中的第一个字符模式,但不更改文件名中其他位置的相同模式

更改文件名中的第一个字符模式,但不更改文件名中其他位置的相同模式

在 Linux 服务器上,我有一个目录,里面全是名称以数字开头的文件。有些文件以两个零开头,例如 00305005。我正在编写一个 bash shell 脚本,其中一个步骤是将所有以 00 开头的文件重命名为以 @0 开头的文件。我之前提到的文件将是 @0305005。

我遇到的问题是,当我尝试重命名文件时,我最终将文件名中的所有 00 实例更改为 @0,如下所示:@0305@05。我一直在使用以下代码,但我不知道如何修复它:

for f in 00*; do mv "$f" "${f//00/@0}"; done

答案1

当你使用时${var//pattern/replacement}//意思是“替换全部出现”。在这种情况下,您只想替换第一次出现的内容,因此您可以只使用/。或者,你甚至可以更具体,使用/#,它将仅在字符串的开头进行替换;这应该不会有什么区别,因为你只处理以开头的文件00,但我倾向于使用它来明确目标。这是一个演示:

$ f=00305005
$ echo "${f//00/@0}"    # // = replace all
@0305@05
$ echo "${f/00/@0}"     # /  = replace first one -- this does what you want
@0305005
$ echo "${f/#00/@0}"    # /# = replace at beginning -- this also does what you want
@0305005
$ g=90305005            # Let's test with a name that *doesn't* start with 00
$ echo "${g/00/@0}"     # / replaces the first match, no matter where it is in the string
90305@05
$ echo "${g/#00/@0}"    # /# does not replace if the beginning does not match
90305005

我还建议使用mv -i任何类型的批量移动/重命名,以避免在发生命名冲突或错误时丢失数据。因此,我建议如下:

for f in 00*; do mv -i "$f" "${f/#00/@0}"; done

答案2

如果您被 shell magic 困住了,那么请尝试使用不同的工具(例如 f.ex)转换文件名。sed

for f in 00*; do
  new_f=$( echo "$f" | sed 's/00/@0/' )
  echo mv "$f" "$f_new"
done

echo我在之前插入了 ,这样您可以在破坏文件之前mv先测试 s 是否正常。然后您可以删除。mvecho

相关内容