你能看懂下面這個macOS命令嗎?(GNU/Linux xargs可能會略有不同)

ls *.JPG | xargs -n1 -I '{}'  convert '{}' -resize "x1600" -profile "/System/Library/ColorSync/Profiles/sRGB Profile.icc" -auto-orient -strip -quality 50 './compact/{}'

解釋一下
ls *.JPG為列出當前目錄所有JPG影象檔案,注意這裡區分大小寫。
| 為管道操作,表示將左邊的結果傳遞給右邊。
xargs為接收管道傳遞值的命令,由於convert不能直接接收管道,所以需要xargs。

上面這個命令的意思是把每一個JPG檔案的檔名依次傳遞給convert命令,傳遞到'{}'的位置。一共有多少個JPG檔案就執行多少次convert的命令。

比如你的目錄裡面有2個檔案,a.JPG和b.JPG,那麼上面的命令就相當於下面的兩行命令:

convert a.JPG -resize "x1600" -profile "/System/Library/ColorSync/Profiles/sRGB Profile.icc" -auto-orient -strip -quality 50 './compact/a.JPG'
convert b.JPG -resize "x1600" -profile "/System/Library/ColorSync/Profiles/sRGB Profile.icc" -auto-orient -strip -quality 50 './compact/b.JPG'

好,再來看一下convert命令,
convert是ImageMagick套件的一個命令,這個套件有非常強大的影象處理功能,這裡我們只介紹上面列出的引數。

第一個引數 '{}'事實上就是透過管道傳進來的JPG檔名,我們以a.JPG為例。

第二個引數表示將a.JPG的高度調節為1600畫素,但長寬比例不變。
resize這個引數經常會用到,所以我多說兩句。假設圖片為4000x2000:
-resize "200%" 長寬同比例縮放到200%,8000x4000
-resize "1000" 寬度調整為1000px,高度同比例調節。調整後尺寸1000x500
-resize "x1000" 高度調整為1000px,寬度同比例調節。調整後尺寸2000x1000
-resize "1000x1000" 長邊調整為1000px,短邊同比例調節。調整後尺寸1000x500
-resize "1000x1000^" 短邊調整為1000px,長邊同比例調節。調整後尺寸2000x1000
-resize "1000x1000!" 寬度高度都調整為1000px,忽略寬高比例。調整後尺寸1000x1000
-resize "1000x1000>" 只有原影象大於1000x1000才調整。
-resize "1000x1000<" 只有原影象小於1000x1000才調整。
光說不練假把式,自己試試就知道啦。

第三個引數表示將影象轉碼為sRGB色彩空間。色彩空間的概念這裡先不贅述了,以後有機會寫篇文章。
簡單來說,單反相機的照片一般你可以選擇aRGB或者sRGB,而iphone拍出來的照片一般都是蘋果自己的p3空間的。sRGB為web標準色彩空間,一般也是預設的色彩空間。

第四個引數表示根據影象exif中的旋轉資訊把影象旋轉。因為有些相機,無論你橫排還是豎拍,圖片存檔都是橫置的,圖片的旋轉資訊是根據裝置的重力感知系統記錄到exif資訊上的。

第五個引數是去掉圖片的exif等profile資訊。這也是為什麼需要前兩個引數進行轉換,否則你直接用-strip來去掉exif資訊會丟掉色彩空間資訊和旋轉資訊。刪掉exif一方面是會縮小體積,另一方面也是避免了一些隱私的暴露,比如位置資訊等。

第六個引數表示JPG壓縮質量為50。數值為1-100之間,數值越大畫質越好,體積越大。

第七個引數為轉換後文件的位置。儲存在當前目錄下面compact目錄下的同名檔案a.jpg。你需要提前建立好compact子目錄。

好了,你能根據自己的需要修改這條命令了嗎?
ImageMagick是一款非常強大的開源圖片處理工具。macOS出廠時並沒有安裝這款軟體,因此你需要自己將它安裝到Mac上,推薦使用brew安裝。

老張說:

如果檔名有空格的話,上面的命令會出錯的,你知道怎麼解決嗎?

ls *.JPG | tr \\n \\0 | xargs -n1 -0 -I '{}'  convert '{}' -resize "x1600" -profile "/System/Library/ColorSync/Profiles/sRGB Profile.icc" -auto-orient -strip -quality 50 './compact/{}'

再說一下xargs吧。

ls *.JPG | xargs命令預設是-n5000,啥意思呢?也就是說,先把ls的結果以空格或者換行來分割成n條記錄,xargs預設一次接受5000條記錄。這顯然不是我們想要的。所以我加上了-n1的引數,就是說,我們一條記錄一條記錄來,有幾個檔案我們就傳遞幾次。

正常來說這沒問題,但是如果檔案中有空格就出問題了。

比如有個’c d.JPG’的檔案。那麼這個檔案會被中間的空格分割成2條記錄,c和d.JPG。也就是說會分兩次傳遞出去。
顯然目錄裡即沒有檔案c,也沒有檔案d.JPG。因此會出錯。

如果恰巧你的目錄裡有檔案c和d.JPG,

如果c也是一個影象檔案的話,那麼雖然也不會報錯,但是’c d.JPG’檔案本身並不會被傳遞處理,
同時c會被額外處理(因為ls列出的JPG檔案本身是不包括c的,因此c本來不會被處理),
而d.JPG會被處理2遍。(d.JPG本身就會被ls列出來傳給管道)
如果c不是影象檔案,那麼convert也會報錯。

所以我們先加上了ls *.JPG | tr \\n \\0。啥意思呢,就是說,先把ls輸出中的換行替換成null。
你看這裡管道就不需要xargs命令,因為tr命令本身能夠接受管道傳過來的資料。

注意,雖然ls命令顯示的檔名可能看上去在同一行,但其實每一個檔名後面都是有換行的。
不信你用ls > a把結果輸出到檔案a,然後檢視一下檔案。

光把換行替換了還是不行,xargs還不知道呀。因此xargs後面又加上了-0這個引數,意思是,嘿xargs,不要用空格和換行來分割記錄了,統一用null來分割吧。這樣,每一個檔案就會被分割成一條記錄透過管道傳遞給convert命令了。

支援我們

如果您喜欢这篇文章,您可以分享给您的朋友,分享到您的社交账号比如:

或者 点击这个链接 观看广告支持我【广告内容与我们无关,请不要轻易相信并打开弹出的广告】。
若您经济宽裕,更欢迎通过下面的方式小额赞助以支持我们的创作。