題 在Linux中批量轉換PNG到JPG


有誰知道在Linux中批量轉換一堆PNG到JPG的好方法? (我正在使用Ubuntu)。

我可以放入shell腳本的png2jpg二進製文件是理想的。


142
2017-11-16 02:06


起源




答案:


你最好的選擇是使用 ImageMagick的

我不是實際使用的專家,但我知道你幾乎可以做任何與此相關的圖像!

一個例子是:

convert image.png image.jpg

它將保留原始圖像以及創建轉換後的圖像。至於批次。我認為您需要使用Mogrify工具(在imagemagick中使用相同的命令行)。請記住這一點 覆寫 舊的圖像。

命令是:

mogrify -format jpg *.png  

214
2017-11-16 02:15



太棒了,這正是我所追求的,並將再次使用。順便說一句,只是為了澄清,因為我沒有意識到這就是你的意思:轉換用於生成單獨的輸出文件,mogrify用於修改原始圖像。 - nedned
具有透明背景的png圖像無法正確轉換為jpg。 - vishnu
要使用透明背景轉換PNG,請使用以下命令: mogrify -format jpg -background black -flatten *.png - hyperknot
@KevinCox在我的linux機箱之後 mogrify -format jpeg img.png 我有2個文件和 file img.* 報告一個png,原始未觸及的,以及一個新的jpeg。所以 mogrify 不 不 在這種情況下覆蓋原始文件。 - neurino
從 mogrify 文件:“這個工具類似於 convert 除了原始圖像文件被覆蓋(除非您使用。更改文件後綴) -格式 選項)您要求的任何更改。“ - janko-m


我還有幾個解決方案。

最簡單的解決方案就像大多數已發布的一樣。一個簡單的bash for循環。

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

出於某種原因,我傾向於避免bash中的循環,所以這裡是一個更加unixy的xargs方法,使用bash進行名稱修改。

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

我使用的那個。它使用GNU Parallel一次運行多個作業,從而提高性能。它默認安裝在許多系統上,幾乎肯定在你的回購中(這是一個很好的程序)。

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

作業數默認為您擁有的進程數。我在雙核系統上使用3個作業找到了更好的CPU使用率。

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

如果你想要一些統計數據(ETA,工作完成,平均每個工作時間......)

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

如果您使用GNU Parallel,還有另一種語法。

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

和其他一些版本(包括debian)類似的語法。

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

70
2018-01-28 02:45



+1中正確的bash字符串擴展在for中,如果我可以給你另一個upvote提及parallel,我會的。但是有一個錯字 - 你需要一個 done 在for循環結束時。此外,對於並行的東西,你可以避免使用它 ls和管道的結構如下: parallel -j 3 --eta convert '{}' '{.}.jpg' ::: *.png (看到 這裡) - evilsoup
修正了拼寫錯誤。這是一個很酷的語法,我不知道。我不知道哪一個我更喜歡可能是因為我不喜歡在bash中使用循環。我把它解決了,因為它可能是更“正確”的方式,但我可能會堅持使用 ls 我自己的方法,因為它對我更有意義。 - Kevin Cox
...雖然應該注意,該語法僅適用於GNU並行。在一些Linux發行版(如Debian和Ubuntu)中打包的並行實際上是一個不同的版本,語法略有不同(使用 -- 而不是 :::) - 即便如此,它令人沮喪地缺乏GNU並行的一些功能。 - evilsoup
(雖然那些沒有打包GNU parallel的發行版上的那些可以很容易地從源代碼安裝它,使用說明 這裡) - evilsoup
我想我應該改變它,以便它可以使用盡可能多的版本。 - Kevin Cox


convert 在許多Linux發行版上找到的命令是作為ImageMagick套件的一部分安裝的。這是運行的bash代碼 convert 在目錄中的所有PNG文件上,避免雙重擴展問題:

for img in *.png; do
    filename=${img%.*}
    convert "$filename.png" "$filename.jpg"
done

25
2017-11-16 03:28



根據轉換的手冊頁:“轉換程序是ImageMagick(1)工具套件的成員。” - nedned
你是對的。出於某種原因,我認為它是不同圖書館的一部分。無論哪種方式,上面發布的代碼都是在目錄中自動執行批量轉換的正確方法。 - Marcin
您可以使用bash擴展來改進該命令,如: for f in *.png; do convert "$f" "${f/%png/jpg}"; done - evilsoup
只記得它是區分大小寫的。我的相機將它命名為* .JPG並且在第一時間沒有意識到這一點。 - tsenapathy


實際上 ”png2jpg“你正在尋找的命令實際上分為兩個命令 pngtopnm 和 cjpeg,他們是一部分 netpbm 和 libjpeg-progs 包,分別。

png2pnm foo.png | cjpeg > foo.jpeg

7
2017-11-16 05:29





TL;博士

對於那些只想要最簡單命令的人:

兌換 和 保持 原始文件:

mogrify -format jpg *.png

兌換 和 去掉 原始文件:

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

批量轉換解釋

有點遲到了,但只是為了清除那些可能對cli不太滿意的人的困惑,這裡有一個超級愚蠢的參考和解釋。

示例目錄

bar.png
foo.png
foobar.jpg

簡單轉換

保留所有原始png文件以及創建jpg文件。

mogrify -format jpg *.png

結果

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

說明

  • mogrify 是的一部分 ImageMagick的 一套圖像處理工具。
    • mogrify處理圖像 到位,意味著原始文件被覆蓋,除了 -format 選項。 (從 網站This tool is similar to convert except that the original image file is overwritten (unless you change the file suffix with the -format option)
  • - format option指定您將更改格式,下一個參數需要是類型(在本例中為jpg)。
  • 最後, *.png 是輸入文件(所有以.png結尾的文件)。

轉換和刪除

將所有png文件轉換為jpg,刪除原始文件。

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

結果

bar.jpg
foo.jpg
foobar.jpg

說明

  • 第一部分與上面完全相同,它將創建新的jpg文件。
  • && 是一個布爾運算符。簡而言之:
    • 當程序終止時,它返回退出狀態。的狀態 0 意味著沒有錯誤。
    • 以來 && 施行 短路評估,只有在以下情況下才會執行正確的部分 沒有錯誤。這很有用,因為如果轉換它們時出錯,您可能不想刪除所有原始文件。
  • rm 命令刪除文件。

花哨的東西

現在這裡有一些人的好東西  適合cli。

如果您在轉換文件時需要一些輸出:

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

轉換所有子目錄中的所有png文件,並為每個子目錄提供輸出:

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

轉換所有子目錄中的所有png文件,將所有生成的jpgs放入 all 目錄,編號,刪除原始png文件,並顯示每個文件的輸出:

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

7
2017-10-17 15:02



可能是你擺脫了最好的答案 while read 部分(替換它或將它們全部一起移除)...... - don_crissti
@don_crissti,讀書時出了什麼問題? - Steven Jeffries
這很容易出錯(除非你100%確定你正在處理合理的文件名)並且速度很慢(比如非常非常非常慢)。 - don_crissti
什麼是默認的JPG質量,以及如何保留文件時間戳? - Dan Dascalescu
@DanDascalescu上面的方法(除了最後一個)將保留文件名,但替換它們的擴展名,因此帶時間戳的文件應該沒問題(總是先複製並測試)。根據ImageMagick,“默認情況下,如果可以確定,則使用輸入圖像的估計質量,否則為92”(imagemagick.org/script/command-line-options.php#quality)可以使用-quality <number>指定質量,其中<number>為1到100。 - Steven Jeffries


find . -name "*.png" -print0 | xargs -0 mogrify -format jpg -quality 50

4
2017-10-13 17:12



感謝深度/遞歸目錄的單行解決方案,它留下了結果 *.jpg 原文旁邊的文件 *.png 文件,顯示如何減少文件大小/質量,並且不會因目錄或文件名中的任何奇怪字符而中斷​​。 - Joel Purra


我的快速解決方案 for i in $(ls | grep .png); do convert $i $(echo $i.jpg | sed s/.png//g); done


3
2018-05-07 12:42



這必須是我見過的最醜陋,最複雜的命令行之一 - evilsoup
@evilsoup老實說,這對shell腳本來說很優雅。聲稱它是錯綜複雜的是不公平的。 - Max Howell
@MaxHowell男子。不。這是一個優雅的版本: for f in ./*.png; do convert "$f" "${f%.*}.jpg"; done。這避免了完全不必要的 ls, grep 和 sed 電話(和 echo,但IIRC是一個內置的bash,所以沒有/很少的性能影響),並擺脫兩個管道和兩個子殼, 和 涉及較少打字。它甚至更輕便,因為不是所有版本的 ls 解析是安全的。 - evilsoup
@evilsoup我的立場得到了糾正!做得好。 - Max Howell


對於批處理:

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

你最終會得到像image1.png.jpg這樣的文件名。

這將適用於bash,也許是bourne。我不知道其他shell,但唯一的區別可能是循環語法。


2
2017-11-16 02:28





許多年來為時已晚,有一個 png2jpeg 專門用於此目的的實用程序,我撰寫。

通過@Marcin調整代碼:

#!/bin/sh

for img in *.png
do
    filename=${img%.*}
    png2jpeg -q 95 -o "$filename.jpg" "$filename.png"
done

2
2017-10-22 09:37





當文件跨越多個目錄時,這就是我用來轉換的內容。我原來的是TGA到PNG

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

這個概念就是你 find 你需要的文件,剝離擴展,然後重新添加 xargs。所以對於PNG到JPG,你要改變擴展並做一個額外的事情來處理alpha通道,即設置背景(在這個例子中是白色,但你可以改變它)然後展平圖像

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

0
2017-09-17 02:34