Batch konwertujący PNG na JPG w systemie Linux

162

Czy ktoś zna dobry sposób na grupową konwersję kilku plików PNG na pliki JPG w systemie Linux? (Używam Ubuntu).

Plik binarny png2jpg, który mógłbym po prostu umieścić w skrypcie powłoki, byłby idealny.

Nedned
źródło

Odpowiedzi:

235

Najlepszym rozwiązaniem byłoby użycie Imagemagick

Nie jestem ekspertem w zakresie rzeczywistego użytkowania, ale wiem, że możesz zrobić prawie wszystko z tym związane!

Przykładem jest:

convert image.png image.jpg

i zachowa oryginał, a także utworzy przekonwertowany obraz. Co do partii. Myślę, że musisz użyć narzędzia Mogrify (z tego samego wiersza poleceń, gdy jest w imagemagick). Pamiętaj, że to zastępuje stare obrazy.

Polecenie to:

mogrify -format jpg *.png  
William Hilsum
źródło
7
Wspaniale, właśnie tego chciałem i będę używał ponownie. Nawiasem mówiąc, aby wyjaśnić, ponieważ nie zdawałem sobie sprawy z tego, co miałeś na myśli: konwersja służy do generowania osobnego pliku wyjściowego, mogrify służy do modyfikowania oryginalnego obrazu.
nedned
1
Obrazy png z przezroczystym tłem nie konwertują się poprawnie do formatu jpg.
Visnu
4
Aby przekonwertować pliki PNG z przezroczystym tłem, użyj następującego polecenia:mogrify -format jpg -background black -flatten *.png
hyperknot
3
@KevinCox na moim linuksie po tym, mogrify -format jpeg img.pngjak mam 2 pliki i file img.*zgłasza jeden png, oryginalny nietknięty i nowy jpeg. Tak mogrifynie nie nadpisać oryginalnych plików w tym przypadku.
neurino
4
Z mogrifydokumentacji: „ To narzędzie jest podobne do converttego, że oryginalny plik obrazu jest zastępowany (chyba że zmienisz sufiks pliku za pomocą opcji -format ) wraz ze wszystkimi
żądanymi
81

Mam jeszcze kilka rozwiązań.

Najprostsze rozwiązanie jest jak większość już opublikowanych. Prosty bash dla pętli.

for i in *.png ; do convert "$i" "${i%.*}.jpg" ; done

Z jakiegoś powodu staram się unikać pętli w bashu, więc tutaj jest bardziej unikalne podejście xargs, używając bash do manglingu nazw.

ls -1 *.png | xargs -n 1 bash -c 'convert "$0" "${0%.*}.jpg"'

Ten, którego używam. Używa GNU Parallel do uruchamiania wielu zadań jednocześnie, co zapewnia wzrost wydajności. Jest instalowany domyślnie na wielu systemach i prawie na pewno znajduje się w twoim repozytorium (jest to dobry program do obejrzenia).

ls -1 *.png | parallel convert '{}' '{.}.jpg'

Domyślnie liczba zadań odpowiada liczbie prowadzonych procesów. Znalazłem lepsze wykorzystanie procesora przy użyciu 3 zadań w moim systemie dwurdzeniowym.

ls -1 *.png | parallel -j 3 convert '{}' '{.}.jpg'

A jeśli chcesz trochę statystyk (ETA, ukończone zadania, średni czas na zadanie ...)

ls -1 *.png | parallel --eta convert '{}' '{.}.jpg'

Istnieje również alternatywna składnia, jeśli używasz GNU Parallel.

parallel convert '{}' '{.}.jpg' ::: *.png

I podobna składnia dla niektórych innych wersji (w tym debian).

parallel convert '{}' '{.}.jpg' -- *.png
Kevin Cox
źródło
2
+1 za prawidłowe rozwinięcie ciągu bash w for, gdybym mógł dać ci kolejny głos za wspomnienie o równoległości, zrobiłbym to. Jest jednak jedna literówka - donena końcu potrzebujesz pętli. Ponadto, dla równoległych rzeczy, możesz uniknąć używania tego lsi fajki z konstrukcją podobną do: parallel -j 3 --eta convert '{}' '{.}.jpg' ::: *.png(patrz tutaj )
evilsoup
Naprawiono literówkę. To fajna składnia, której nie znałem. Nie wiem, który bardziej mi się podoba, prawdopodobnie z tego samego powodu, dla którego wolę nie używać pętli w bash. Postawiłem to rozwiązanie, ponieważ jest to prawdopodobnie bardziej „właściwy” sposób, ale prawdopodobnie będę trzymać się tej lsmetody dla siebie, ponieważ ma to dla mnie większy sens.
Kevin Cox
1
... chociaż należy zauważyć, że ta składnia działa tylko na GNU równolegle. Paralela spakowana w niektórych dystrybucjach linuksowych (takich jak Debian i Ubuntu) jest w rzeczywistości inną wersją z nieco inną składnią ( --raczej użyj niż :::) - a nawet wtedy frustrująco brakuje niektórych funkcji GNU równoległych.
evilsoup
(chociaż osoby na dystrybucjach, które nie zawierają GNU równoległego, mogą dość łatwo zainstalować go ze źródła, korzystając z instrukcji tutaj )
evilsoup 28.01.2013
Myślę, że powinienem go wtedy zmienić, aby działał z jak największą liczbą wersji.
Kevin Cox
26

convertKomenda znaleźć na wielu dystrybucjach systemu Linux jest zainstalowany jako część pakietu ImageMagick. Oto kod bash do uruchomienia convertna wszystkich plikach PNG w katalogu i uniknięcia problemu podwójnego rozszerzenia:

for img in *.png; do
    filename=${img%.*}
    convert "$filename.png" "$filename.jpg"
done
Marcin
źródło
8
Według strony podręcznika do konwersji: „Program do konwersji należy do zestawu narzędzi ImageMagick (1)”.
nedned
1
Masz rację. Z jakiegoś powodu myślałem, że to część innej biblioteki. Tak czy inaczej kod, który opublikowałem powyżej, jest prawidłowym sposobem zautomatyzowania konwersji wsadowej w katalogu.
Marcin
2
Możesz użyć rozszerzenia bash, aby ulepszyć to polecenie, takie jak:for f in *.png; do convert "$f" "${f/%png/jpg}"; done
evilsoup
pamiętaj tylko, że wielkość liter ma znaczenie. mój aparat nazwał to * .JPG i nie zdawałem sobie z tego sprawy w pierwszej instancji.
tsenapathy
10

tl; dr

Dla tych, którzy chcą tylko najprostszych poleceń:

Konwertuj i zachowuj oryginalne pliki:

mogrify -format jpg *.png

Konwertuj i usuwaj oryginalne pliki:

mogrify -format jpg *.png && rm *.png

Wyjaśnienie przetwarzania wsadowego

Trochę późno na imprezę, ale aby wyjaśnić zamieszanie komuś, kto może nie czuć się komfortowo z cli, oto super głupie odniesienie i wyjaśnienie.

Przykładowy katalog

bar.png
foo.png
foobar.jpg

Prosta konwersja

Przechowuje wszystkie oryginalne pliki png, a także tworzy pliki jpg.

mogrify -format jpg *.png

Wynik

bar.png
bar.jpg
foo.png
foo.jpg
foobar.jpg

Wyjaśnienie

  • mogrify jest częścią pakietu narzędzi ImageMagick do przetwarzania obrazów.
    • mogrify przetwarza obrazy w miejscu , co oznacza, że ​​oryginalny plik jest zastępowany, z wyjątkiem -formatopcji. (Z witryny : This tool is similar to convert except that the original image file is overwritten (unless you change the file suffix with the -format option))
  • - formatOpcja określa, że będzie zmiana formatu, a następnego Argument musi być typu (w tym przypadku, jpg).
  • Na koniec *.pngsą pliki wejściowe (wszystkie pliki z rozszerzeniem .png).

Konwertuj i usuwaj

Konwertuje wszystkie pliki png na jpg, usuwa oryginał.

mogrify -format jpg *.png && rm *.png

Wynik

bar.jpg
foo.jpg
foobar.jpg

Wyjaśnienie

  • Pierwsza część jest dokładnie taka sama jak powyżej, stworzy nowe pliki jpg.
  • Jest &&to operator logiczny. W skrócie:
    • Po zakończeniu programu zwraca status wyjścia. Status 0oznacza brak błędów.
    • Ponieważ &&wykonuje ocenę zwarcia , odpowiednia część zostanie wykonana tylko wtedy, gdy nie wystąpią błędy . Jest to przydatne, ponieważ możesz nie chcieć usunąć wszystkich oryginalnych plików, jeśli wystąpił błąd podczas ich konwersji.
  • rmPolecenie usuwa pliki.

Fantazyjne rzeczy

Oto kilka korzyści dla osób, które czują się komfortowo z cli.

Jeśli chcesz uzyskać dane wyjściowe podczas konwersji plików:

for i in *.png; do mogrify -format jpg "$i" && rm "$i"; echo "$i converted to ${i%.*}.jpg"; done

Konwertuj wszystkie pliki png we wszystkich podkatalogach i podaj dane wyjściowe dla każdego:

find . -iname '*.png' | while read i; do mogrify -format jpg "$i" && rm "$i"; echo "Converted $i to ${i%.*}.jpg"; done

Konwertuj wszystkie pliki png we wszystkich podkatalogach, umieść wszystkie wynikowe pliki jpg w allkatalogu, numeruj je, usuwaj oryginalne pliki png i wyświetlaj dane wyjściowe dla każdego pliku, gdy ma to miejsce:

n=0; find . -iname '*.png' | while read i; do mogrify -format jpg "$i" && rm "$i"; fn="all/$((n++)).jpg"; mv "${i%.*}.jpg" "$fn"; echo "Moved $i to $fn"; done
Steven Jeffries
źródło
Prawdopodobnie najlepsza odpowiedź, pod warunkiem, że pozbędziesz się while readczęści (wymień ją lub usuniesz wszystkie razem) ...
don_crissti
@don_crissti, co jest nie tak z czytaniem?
Steven Jeffries
Jest podatny na błędy (chyba że masz 100% pewności, że masz do czynienia z rozsądnymi nazwami plików) i powolny (jak w przypadku bardzo, bardzo, bardzo wolnych).
don_crissti
Jaka jest domyślna jakość JPG i jak można zachować sygnatury czasowe plików?
Dan Dascalescu
@DanDascalescu Powyższe metody (oprócz ostatniej) zachowają nazwy plików, ale zastąpią ich rozszerzenie, więc pliki ze znacznikiem czasu powinny być w porządku (zawsze najpierw wykonaj kopię i przetestuj). Według ImageMagick: „Domyślnie używana jest szacunkowa jakość obrazu wejściowego, jeśli można ją określić, w przeciwnym razie 92” ( imagemagick.org/script/command-line-options.php#quality ) Jakość można określić za pomocą opcji -quality <numer> gdzie <numer> to 1 do 100.
Steven Jeffries
8

Rzeczywiste png2jpgpolecenie, którego szukasz, jest w rzeczywistości podzielone na dwa polecenia o nazwie pngtopnmi cjpeg, i są one odpowiednio częścią pakietów netpbmi libjpeg-progs.

png2pnm foo.png | cjpeg > foo.jpeg
Miś
źródło
6
find . -name "*.png" -print0 | xargs -0 mogrify -format jpg -quality 50
emdog4
źródło
1
Dzięki za jednokreskowe rozwiązanie głębokiego / rekurencyjnego katalogu, który pozostawia *.jpgpliki wynikowe obok oryginalnych *.pngplików, pokazuje, jak zmniejszyć rozmiar / jakość pliku i nie pęka z powodu nieparzystych znaków w nazwie katalogu lub pliku.
Joel Purra
5

moje szybkie rozwiązanie for i in $(ls | grep .png); do convert $i $(echo $i.jpg | sed s/.png//g); done

max
źródło
2
To musi być jedna z najbrzydszych, najbardziej
zawiłych
1
@evilsoup szczerze mówiąc, jest to eleganckie skrypty powłoki. Twierdzenie, że jest zawiłe, jest niesprawiedliwe.
Max Howell,
8
@ MaxHowell man. Nie. Tu będzie elegancka wersja to: for f in ./*.png; do convert "$f" "${f%.*}.jpg"; done. Że unika się całkowicie zbędne ls, grepa sedpołączenia (a echo, ale IIRC to jest wbudowane bash i tak nie będzie miał / bardzo mały wpływ na wydajność) i pozbywa się z dwóch rur i dwóch podpowłok, a wiąże się z mniej pisać. Jest nawet nieco bardziej przenośny, ponieważ nie wszystkie wersje lsmożna bezpiecznie analizować.
evilsoup
@evilsoup Stoję poprawiony! Dobra robota.
Max Howell,
4

Wiele lat za późno, istnieje narzędzie png2jpeg specjalnie do tego celu, którego jestem autorem.

Dostosowanie kodu przez @Marcin:

#!/bin/sh

for img in *.png
do
    filename=${img%.*}
    png2jpeg -q 95 -o "$filename.jpg" "$filename.png"
done
użytkownik7023624
źródło
3

Do przetwarzania wsadowego:

for img in *.png; do
  convert "$img" "$img.jpg"
done

Skończysz z nazwami plików, takimi jak image1.png.jpg.

Będzie to działać w trybie bash, a może bourne. Nie wiem o innych powłokach, ale jedyną różnicą byłaby prawdopodobnie składnia pętli.

Jeffrey Aylesworth
źródło
1

To jest to, czego używam do konwersji, gdy pliki obejmują więcej niż jeden katalog. Mój oryginalny to TGA na PNG

find . -name "*.tga" -type f | sed 's/\.tga$//' | xargs -I% convert %.tga %.png

Chodzi o to, findże potrzebujesz plików, usuń rozszerzenie, a następnie dodaj je ponownie xargs. W przypadku PNG na JPG zmieniłbyś rozszerzenia i zrobiłeś jedną dodatkową rzecz, aby poradzić sobie z kanałami alfa, mianowicie ustawiając tło (w tym przykładzie białe, ale możesz je zmienić), a następnie spłaszczyć obraz

find . -name "*.png" -type f | sed 's/\.png$//' | xargs -I% convert %.png -background white -flatten  %.jpg
Archimedes Trajano
źródło