Come sostituire più di una sottostringa contemporaneamente in bash?

Ho una directory contenente file di immagine che devono essere riprodotti in bash. Durante leco, voglio sostituire sia il nome del file che lestensione nel comando a riga singola.

File di esempio:

images/file_name_1.jpg images/file_name_2.jpg 

Normalmente, posso fare una singola sostituzione in questo modo:

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

E loutput diventa:

 images/image_name_1.jpg images/image_name_2.jpg  

Come posso mantenerlo nel ciclo for e sostituire anche la stringa “jpg” con “png”? È solo unistanza, potrei sostituire il punto con la virgola ecc.

Quando provo questo:

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

Non funziona. Non riesco a trovare altre soluzioni o idee. È possibile, se sì, come?

Commenti

  • Non ' Non so perché ' t ha funzionato in bash, ma le sostituzioni annidate funzionano proprio come ci si aspettava in zsh. A seconda del proprio ambiente, si potrebbe prendere in considerazione lutilizzo di un shell migliore;)

Risposta

Lapproccio semplice sarebbe assegnare il risultato a una variabile, quindi lavorare con quella variabile. Esempio:

 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  

Commenti

  • Questa risposta non è completa. le sostituzioni verranno applicate ovunque nelle stringhe del nome del file. In base alla domanda, Kubilay vuole sostituire un prefisso e unestensione (suffisso). Puoi modificare e tenerne conto : $ {var / # Pattern / Replacement} Se il prefisso di var corrisponde a Pattern, allora sostituisci il Pattern. $ {var /% Pattern / Replacement} If il suffisso di var corrisponde a Pattern, quindi sostituisci Sostituzione con Pattern.
  • @rMistero Non cè ' regola che vieti di inviare unaltra risposta solo perché una risposta è stata accettata. In effetti, penso che dovresti, soprattutto perché la semantica di ciò che stai proponendo è diversa. Detto questo, questo è il modo per fare ciò che lOP ha detto dopo aver provato, quindi anche se ci sono altri risultati che potrebbero essere validi, credo sia lecito ritenere che questo sia in linea con ciò che lOP voleva ottenere. / li>

Risposta

Puoi assegnare la sostituzione precedente a una variabile ed eseguire la sostituzione su quella variabile invece

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

Commenti

  • Non sono sicuro se funziona. " for i in images / *; fare j = {i / jpg / png} echo $ {j / file / immagine}; done " echi " {i / jpg / png} " ripetutamente.
  • Ora sì: " for i in images / *. jpg; fare j = $ {i / jpg / png}; echo $ {j / file / immagine}; fatto ". Grazie!

Rispondi

per modificare qualsiasi stringa :

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

una scorciatoia da rinominare (che potrebbe essere lobiettivo finale:

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

Commenti

  • Penso ancora che invocare Perl una volta per ogni file sia eccessivo, ma almeno ora questo dà una risposta alla domanda. 🙂
  • @MichaelKj ö rling Non ' è necessario richiamare Perl per ogni file, puoi fare rename … images/*. Ma questo richiede una distribuzione basata su Debian (rename su altre varianti di Linux è un comando completamente diverso).
  • @Gilles Stavo pensando di più alla prima versione, soprattutto dal momento che ' non cè nulla nella domanda posta sulla ridenominazione dei file. La versione originale (modificata nel periodo di grazia) di questa risposta conteneva solo il rename suggerimento di comando.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *