重命名一堆文件,更改几个子字符串

重命名一堆文件,更改几个子字符串

我有一堆名称类似于 image(1) image(2) image(3) 的文件。我想沿着 image1.jpg image2.jpg 等重命名它们。我可以通过大括号分两步完成,这显然是某种内置的 shell 提供的字符串替换功能的行

orig="a_string"
mod=${orig/string/new_thing}

它将 a_string 转换为 a_new_thing。因此,在 for 循环中使用它,我可以将 ) 转换为 .jpg

for f in *; do mv $f "${f/)/.jpg}" ;done

进而

for f in *; do mv $f "${f/\(/}" ;done

删除 (。开括号必须被转义,我想否则 shell 会认为它是其他东西的开始。闭括号不必像这样转义。所以我的问题是,是否有一个单行或者其他更好的方法来做到这一点,比如使用管道。如果文件名中的括号把事情弄乱了,那么暂时假设这些括号被删除,留下用两个其他字符串替换两个子字符串的简单问题。

答案1

您可以使用命令重命名多个文件rename。在这种情况下,可行的解决方案可能是:

rename 's/\(//; s/\)/.jpeg/;' image*

答案2

您可以使用双斜杠一次更改多项内容。

for f in * ; do mv "$f" "${f//[()]/}.jpg" ; done

答案3

我将解决您的一般问题,即如何进行多次替换(特别是在重命名中,尽管这可能适用于其他上下文)。我假设您有一堆名称中包含单词“over”和“dog”的文件,并且您想分别将它们替换为“under”和“cat”。

蛮力:

for f in *
do
    g=${f/over/under}
    h=${g/dog/cat}
    mv -- "$f" "$h"
done

(这可以--保护您免受以以下开头的文件名可能导致的不良行为的影响-mv -- "$f" "$h".jpg如果需要,请将最后一行更改为。)请注意,如果文件名包含仅有的“超过”或者 “狗”(但不是两者),这将只进行一个可用的替换。如果它包含“dog”和“over”(按该顺序),它仍然会进行替换。在您提出的情况下,您的字符串是“(”和“)”,您可能不喜欢这些行为。

聚苯乙烯实际上,您应该mv像这样保护命令:

if [ "$f" != "$h" ]
然后
    如果[-e“$h”]
    然后
        (错误处理)
    别的
        mv——“$f”“$h”
完毕

以避免在尝试将文件重命名为自身时收到错误消息(因为其名称不包含任何一个字符串),并避免破坏现有文件(例如,如果您有一个image(1)文件并且您也已经有一个image1.jpg文件)。

sed

for f in *
do
    g=$(sed 's/\(.*\)over\(.*\)dog\(.*\)/\1under\2cat\3/' <<< "$f")
    mv -- "$f" "$g"
done

这与第一个相反:仅当“超过”时才进行替换“狗”两个都出现(按该顺序),而不是其他情况。

(“here string”)语法<<<并不适用于所有 shell。要在不支持此处字符串的 shell 中执行上述操作,请执行以下操作:

for f in *
do
    g=$(printf "%s" "$f" | sed 's/\(.*\)over\(.*\)dog\(.*\)/\1under\2cat\3/')
    mv -- "$f" "$g"
done

相关内容