しぐまろぐ

勉強したことや読んだ本について書きます。

シェル・ワンライナー160本ノック 問題2

問題2:画像ファイルの一括変換

2/imgディレクトリ以下にあるPNG形式の画像を、convertで全てJPEG形式に変換する

解答(誤答)

練習1.3.fなどを参考にして書いた。

$  find *.png | xargs -I@ convert @ @.jpg | sed -E 's/\.png.jpg$/\.jpg/g'
10_black.png.jpg
11_steelblue.jpg
11_steelblue.png
11_steelblue.png.jpg
......
  • Iオプション:標準入力より渡されたデータを xargsの引数と置き換える。記号は@でなくてもなんでも良い。

拡張子がpngのファイル名をfindして、結果をコンバートし、その後で.png.jpgになってしまったファイル名を変更する。という方法を考えたのだが、うまくいかず、.png.jpgのままになっている(なんで?)
sedが上手くいかないのも謎だが、そもそも、convertした時点で.png.jpgになってしまうのがいただけない。
→ 2023.01.04追記:カツニャリ (id:papiro)さんに原因についてコメントでご教示いただきました。ありがとうございます。

正答

$ find *.png | sed 's/\.png$//' | xargs -I@ convert @.png @.jpg

先にsedして拡張子を消して、convertするときにそれぞれ拡張子をつける。
正答を見るとなぜこれが思いつかないんだ、と思ってしまう。。
なお、本の正当はfindではなくlsだが、結果は同じだし処理時間もほぼ同じだった。ただ、処理ファイルが多くなると差が広がりそうなので、lsの方が良さそう。

別解

ImageMagickのmogrifyコマンドを使えば簡単に拡張子を変更できる。

$ mogrify -format jpg *.png

感想

Macに元からImageMagickが入ってて驚いた。
また、Macではnprocできないようだ。