Você pode renomear arquivos múltiplos usando o comando rename
. Neste caso, uma solução de trabalho poderia ser:
rename 's/\(//; s/\)/.jpeg/;' image*
Eu tenho um monte de arquivos com nomes como image (1) image (2) image (3). Eu gostaria de renomear aqueles em massa ao longo das linhas de image1.jpg image2.jpg etc. Eu posso fazer isso em duas etapas por meio de chaves, que aparentemente é algum tipo de provisão de shell embutida para substituição de string ao longo das linhas de
orig="a_string"
mod=${orig/string/new_thing}
que leva a_string para a_new_thing. Então, usando isso em um loop for eu posso cuidar de transformar o) em .jpg
for f in *; do mv $f "${f/)/.jpg}" ;done
e depois
for f in *; do mv $f "${f/\(/}" ;done
remove o (. O paren aberto tem que ser escapado, suponho que caso contrário o shell pensa que é o começo de outra coisa. O paren próximo não precisa ser escapado desse jeito. Então, a minha pergunta é, existe um one-liner ou outra maneira melhor de fazer isso, como usar pipes. Se os parêntesis no nome do arquivo estiverem copiando as coisas, então assuma por enquanto que esses parêntesis são removidos, deixando o simples problema de substituir duas substrings por duas outras strings.
Você pode alterar mais de uma coisa por vez usando uma barra dupla.
for f in * ; do mv "$f" "${f//[()]/}.jpg" ; done
Vou abordar sua pergunta geral sobre como fazer várias substituições (especificamente, em uma renomeação, embora isso possa ser aplicável a outros contextos). Eu suponho que você tenha um monte de arquivos cujos nomes incluem as palavras "over" e "dog", e você quer substituí-los por "under" e "cat", respectivamente.
for f in *
do
g=${f/over/under}
h=${g/dog/cat}
mv -- "$f" "$h"
done
(O --
protege você contra comportamento indesejado
Isso pode resultar de um nome de arquivo que começa com -
.
Altere a última linha para mv -- "$f" "$h".jpg
, se desejar.
Observe que, se um nome de arquivo contiver somente , “over” ou “dog”
(mas não ambos), isso fará apenas a substituição disponível.
Se contiver “dog” e “over” (nessa ordem),
ainda fará as substituições.
No caso que você apresentou, onde suas strings são "(" e ")",
você pode não gostar desses comportamentos.
P.S. Realisticamente,
provavelmente você deve proteger o comando mv
assim:
if [ "$f" != "$h" ] then if [ -e "$h" ] then (Error handling) else mv -- "$f" "$h" fi done
para evitar uma mensagem de erro ao tentar renomear um arquivo para si
(porque seu nome não continha das strings),
e para evitar a destruição de um arquivo existente
(por exemplo, se você tiver um arquivo image(1)
e você também já tem um arquivo image1.jpg
).
sed
for f in *
do
g=$(sed 's/\(.*\)over\(.*\)dog\(.*\)/undercat/' <<< "$f")
mv -- "$f" "$g"
done
Este é o oposto do primeiro: faz as substituições apenas se "over" e "dog" ambos aparecerem (nessa ordem) e não o contrário.
A sintaxe <<<
("string aqui") não funciona em todos os shells.
Para fazer o acima em um shell que não suporta aqui strings, faça:
for f in *
do
g=$(printf "%s" "$f" | sed 's/\(.*\)over\(.*\)dog\(.*\)/undercat/')
mv -- "$f" "$g"
done