我有一堆名称类似于 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