Como fazer mais de uma substituição de substring de uma vez no bash?

Tenho um diretório que contém arquivos de imagem que devem ser exibidos no bash. Enquanto ecoando, desejo substituir o nome do arquivo e a extensão no comando de linha única.

Arquivos de exemplo:

images/file_name_1.jpg images/file_name_2.jpg 

Normalmente, posso fazer uma substituição única como esta:

 for i in images/*; do echo ${i/file/image}; done  

E a saída fica como:

 images/image_name_1.jpg images/image_name_2.jpg  

Como posso mantê-lo em loop for e substituir a string “jpg” por “png” também? É apenas uma instância, eu poderia substituir o ponto por vírgula etc.

Quando tento fazer isso:

 for i in images/*; do echo ${{i/jpg/png}/file/image}; done  

Não funciona. Não consegui encontrar nenhuma outra solução ou ideia. Isso é possível -se for, como?

Comentários

  • Não ' não sei por que isso não ' funcionou no bash, mas as substituições aninhadas funcionam exatamente como você esperava no zsh. Dependendo do seu ambiente, você pode considerar o uso de um melhor shell;)

Resposta

A abordagem simples seria atribuir o resultado a uma variável e, em seguida, trabalhar com essa variável. Exemplo:

 for filename in images/* do echo "filename is now $filename" filename=${filename/jpg/png}; echo "filename is now $filename" filename=${filename/file/image}; echo "filename is now $filename" echo "final filename is ${filename}" done  

Comentários

  • Esta resposta não está completa. as substituições serão aplicadas em qualquer lugar nas strings de nome de arquivo. Com base na pergunta, Kubilay deseja substituir um prefixo e uma extensão (sufixo). você pode modificar e levar isso em consideração : $ {var / # Padrão / Substituição} Se o prefixo de var corresponder ao Padrão, então substitua Substituição por Padrão. $ {var /% Padrão / Substituição} Se o sufixo de var corresponde a Padrão, então substitua Substituição por Padrão.
  • @rMistero Não ' s nenhuma regra contra postar outra resposta só porque uma resposta foi aceita. Na verdade, acho que você deveria, especialmente porque a semântica do que você está propondo é diferente. Dito isso, esta é a maneira de fazer o que o OP disse depois de tentar, então, mesmo que haja outros resultados que também possam ser válidos, acredito que é seguro presumir que isso está de acordo com o que o OP queria realizar.

Resposta

Você pode atribuir a substituição anterior a uma variável e executar a substituição dessa variável

 for i in images/* do j=${i/jpg/png} echo ${j/file/image} done  

Comentários

  • Não tenho certeza se isso funcionar. " para i em imagens / *; fazer j = {i / jpg / png} echo $ {j / arquivo / imagem}; done " ecoa " {i / jpg / png} " repetidamente.
  • Agora sim: " para i em images / *. jpg; faça j = $ {i / jpg / png}; echo $ {j / arquivo / imagem}; concluído ". Obrigado!

Responda

para alterar qualquer string :

$ echo "images/file_name_1.jpg" | perl -pE "s/file/image/;s/jpg$/png/;" images/image_name_1.png 

um atalho para renomear (que pode ser o objetivo final:

$ rename "s/file/image/;s/jpg$/png/;" "$i" 

Comentários

  • Eu ainda acho que invocar o Perl uma vez para cada arquivo é um exagero, mas pelo menos agora isso dá uma resposta à pergunta. 🙂
  • @MichaelKj ö rling Você não ' precisa invocar o Perl para cada arquivo, você pode fazer rename … images/*. Mas isso requer uma distribuição baseada em Debian (rename em outras variantes do Linux é um comando completamente diferente).
  • @Gilles Eu estava pensando mais sobre a primeira versão, particularmente porque não há ' nada na pergunta sobre como renomear arquivos. A versão original (edição do período de tolerância) desta resposta tinha apenas a rename sugestão de comando.

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *