Hur byter man ut mer än ett underlag samtidigt i bash?

Jag har en katalog som innehåller bildfiler som ska återges i bash. Medan jag ekar vill jag ersätta både filnamn och förlängning i enradskommando.

Exempel på filer:

images/file_name_1.jpg images/file_name_2.jpg 

Normalt kan jag byta ut så här:

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

Och utdata blir som:

 images/image_name_1.jpg images/image_name_2.jpg  

Hur kan jag hålla det i loop och ersätta ”jpg” -strängen till ”png” också? Det är bara en instans, jag kan ersätta punkten till komma osv.

När jag försöker detta:

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

Det fungerar inte. Jag kan inte hitta någon annan lösning eller idé. Är det möjligt – om så, hur?

Kommentarer

  • Jag don ' vet inte varför detta inte fungerade ' t, men kapslade ersättningar fungerar precis som du förväntade dig i zsh. Beroende på din miljö kan du överväga att använda en bättre skal;)

Svar

Den enkla metoden skulle vara att tilldela resultatet till en variabel och sedan arbeta med den variabeln. Exempel:

 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  

Kommentarer

  • Detta svar är inte fullständigt. substitutionerna kommer att gälla var som helst i filnamnsträngarna. Baserat på frågan vill Kubilay ersätta ett prefix och ett tillägg (suffix). kan du ändra och ta hänsyn till detta : $ {var / # Pattern / Replacement} Om prefixet för var matchar mönstret, ersätt ersättningen med mönstret. $ {var /% Pattern / Replacement} If suffixet av var matchar mönstret, ersätt sedan Ersättningen för mönstret.
  • @rMistero Det finns ' ingen regel mot att skicka ett annat svar bara för att ett svar har accepterats. Jag tror faktiskt att du borde, särskilt eftersom semantiken i det du föreslår är annorlunda. Med detta sagt är det här sättet att göra vad OP sa efter att ha försökt, så även om det finns andra resultat som också kan vara giltiga, tror jag att det är säkert att anta att detta är i linje med vad OP ville uppnå. / li>
  • Svar

    Du kan tilldela den tidigare ersättningen till en variabel och köra ersätt på den variabeln istället

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

    Kommentarer

    • Inte säker om det fungerar. " för i i bilder / *; gör j = {i / jpg / png} echo $ {j / file / image}; gjort " ekar " {i / jpg / png} " upprepade gånger.
    • Nu ja: " för i i bilder / *. jpg; gör j = $ {i / jpg / png}; eko $ {j / fil / bild}; gjort ". Tack!

    Svar

    för att ändra valfri sträng :

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

    en genväg för att byta namn (vilket kan vara det ultimata målet:

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

    Kommentarer

    • Jag tycker fortfarande att det är för mycket att åberopa Perl en gång för varje fil, men åtminstone nu ger det svar på frågan. 🙂
    • @MichaelKj ö rling Du behöver inte ' för att anropa Perl för varje fil, du kan göra rename … images/*. Men detta kräver en Debian-baserad distribution (rename på andra Linux-varianter är ett helt annat kommando).
    • @Gilles Jag tänkte mer på den första versionen, särskilt eftersom det ' inte finns något i frågan som ställs om att byta namn på filer. Den ursprungliga (redigerade respitperioden) versionen av detta svar hade endast kommandoförslaget rename.

    Lämna ett svar

    Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *