Jak wykonać jednoczesną wymianę więcej niż jednego podciągu w bash?

Mam katalog zawierający pliki graficzne, które mają być powtórzone w bash. Podczas echa chcę zamienić zarówno nazwę pliku, jak i rozszerzenie w poleceniu jednowierszowym.

Przykładowe pliki:

images/file_name_1.jpg images/file_name_2.jpg 

Zwykle mogę wykonać jedną zamianę w następujący sposób:

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

Wynik wygląda następująco:

 images/image_name_1.jpg images/image_name_2.jpg  

Jak mogę zachować to w pętli for i zamienić ciąg „jpg” na „png”? To tylko przykład, mógłbym zamienić kropkę na przecinek itp.

Kiedy spróbuję tego:

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

To nie działa. Nie mogę znaleźć innego rozwiązania lub pomysłu. Czy to możliwe – jeśli tak, to w jaki sposób?

Komentarze

  • Nie ' Nie wiem, dlaczego to ' nie działa w bash, ale zagnieżdżone zamienniki działają tak, jak oczekiwano w zsh. W zależności od środowiska możesz rozważyć użycie lepsza powłoka;)

Odpowiedź

Prostym podejściem byłoby przypisanie wyniku do zmiennej, a następnie praca z tą zmienną. Przykład:

 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  

Komentarze

  • Ta odpowiedź nie jest kompletna. Podstawienia zostaną zastosowane w dowolnym miejscu w łańcuchach nazw plików. Na podstawie pytania Kubilay chce zamienić przedrostek i rozszerzenie (sufiks). Czy możesz zmodyfikować i wziąć to pod uwagę : $ {zmienna / # Wzorzec / Zastąpienie} Jeśli przedrostek zmiennej Zmienna pasuje do Wzorca, zamień na Wzorzec Zamiennik. $ {Zmienna /% Wzorzec / Zastąpienie} Jeśli sufiks var pasuje do wzorca, a następnie zamień na zamianę na wzorzec.
  • @rMistero Nie ' nie ma reguły zakazującej publikowania innej odpowiedzi tylko dlatego, że odpowiedź została zaakceptowana. Właściwie myślę, że powinieneś, zwłaszcza że semantyka tego, co proponujecie, jest inna. To powiedziawszy, jest to sposób na zrobienie tego, co powiedział PO, próbując, więc nawet jeśli istnieją inne wyniki, które również mogą być ważne, uważam, że można bezpiecznie założyć, że jest to zgodne z tym, co chciał osiągnąć PO. / li>

Odpowiedź

Możesz przypisać poprzednią zamianę do zmiennej i zamiast tego przeprowadzić zamianę na tej zmiennej

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

Komentarze

  • Nie wiem Jeśli działa. " for i in images / *; do j = {i / jpg / png} echo $ {j / plik / obraz}; wykonane " powtarza " {i / jpg / png} " wielokrotnie.
  • Teraz tak: " for i in images / *. jpg; do j = $ {i / jpg / png}; echo $ {j / plik / obraz}; gotowe ". Dzięki!

Odpowiedz

, aby zmienić dowolny ciąg :

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

skrót do zmiany nazwy (co może być ostatecznym celem:

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

Komentarze

  • Nadal uważam, że wywołanie Perla raz dla każdego pliku jest przesadą, ale przynajmniej teraz daje to odpowiedź na pytanie. 🙂
  • @MichaelKj ö rling Nie ' Nie musisz wywoływać Perla dla każdego pliku, możesz zrobić rename … images/*. Ale to wymaga dystrybucji opartej na Debianie (rename w innych wariantach Linuksa to zupełnie inne polecenie).
  • @Gilles Myślałem więcej o pierwszej wersji, zwłaszcza, że ' nie ma nic w pytaniu o zmianę nazw plików. Oryginalna (edytowana w okresie prolongaty) wersja tej odpowiedzi zawierała tylko sugestię polecenia rename.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *