CSV が Excel で文字化けする原因と直し方(Mac で実測)

会計ソフトから落とした CSV を Excel で開いたら、商品名 のはずの列が 蝠刀蜷 になっていた。逆に、自分が Excel で作って送った CSV を「文字化けしてます」と返された。どちらも経験があるのではないでしょうか。

この 2 つ、立場は正反対ですが、詰まっているところは同じです。CSV というファイルには、中身が何の文字コードで書かれているかを記録する欄がありません。

検体は macOS 26.6.2(ビルド 25G83)と Microsoft Excel for Mac 16.107.2 で、自分で作って実際に開いたり保存したりしたものです。

先に結論

困っている場面 やること
もらった CSV を開いたら化けている ダブルクリックをやめる。データ → データ ファイル指定 (Power Query) → テキスト/CSV から開く
自分が渡す CSV を作る 保存形式で「CSV UTF-8」を選ぶ。ただの「CSV(コンマ区切り)」は選ばない
プログラムに読ませる CSV を作る BOM 付きのままでかまいません。読む側で utf-8-sig を指定してもらいます

よく見かける「Shift_JIS で保存し直す」は入れていません。動くことは動くのですが、戻せない代償があります。

CSV には文字コードを書く欄が無い

商品名,数量,金額 から始まる CSV を UTF-8 で保存して、先頭を覗いてみます。

$ xxd -l 12 utf8_nobom.csv
00000000: e595 86e5 9381 e590 8d2c e695            .........,..

e59586 e59381 e5908d が「商品名」を UTF-8 で符号化したバイト列、2c がカンマです。データがいきなり始まっています。ZIP や画像なら先頭にヘッダがあって「これは何か」を名乗るのですが、CSV にはそれがありません。テキストがそのまま置いてあるだけです。

つまり開く側は、書いていないものを推測するしかない。日本語環境の Excel が最初に疑うのは Shift_JIS 系です。UTF-8 のバイト列を Shift_JIS 系として読むと、こうなります。

$ printf '請求書' | iconv -f CP932 -t UTF-8
隲区アよ嶌

実際に Excel for Mac で開いた画面がこれでした。

セルに入るはずの値 表示された値
商品名 / 数量 / 金額 蝠刀蜷 / 謨ー驥 / 驥鷹。
請求書 隲区アよ嶌
髙橋商店 鬮呎ゥ句膚蠎
①番テーブル 竭逡ェ繝シ繝悶Ν

先頭が 蝠・隲・繝・縺・謨・鬮 あたりで始まっていたら、UTF-8 を Shift_JIS 系として読んだ化け方です。ひらがなの多い言葉は 縺、カタカナは 繝 がよく顔を出します。

BOM が付いていると化けない

ところが、同じ内容でも化けない場合があります。先頭に 3 バイトだけ足したものです。

$ xxd -l 12 utf8_bom.csv
00000000: efbb bfe5 9586 e593 81e5 908d            ............

この ef bb bf が BOM(Byte Order Mark)で、「以下は UTF-8 です」という目印になります。Excel はこれを見て判断を変えます。4 通りの検体を、Finder のダブルクリックと同じ経路で開いた結果です。

検体 結果
UTF-8(BOM なし) 化ける
UTF-8(BOM 付き) 正しく開く
Shift_JIS(CP932) 正しく開く
UTF-16LE(BOM 付き・カンマ区切り) 文字は正しいが、全部 A 列の 1 セルに入る

Microsoft も公式のサポートページで「BOM 付きで保存されていれば UTF-8 の CSV は普通に開ける」と書いています。BOM が唯一の手がかりだ、というのが CSV の文字化けの正体です。

なお file -I は BOM の有無を区別してくれません。BOM あり・なしのどちらも charset=utf-8 と答えます。確かめたいときは上のように xxd -l 3 で先頭 3 バイトを直接見るのが確実です。

もらった CSV が化けているとき

配布元に「BOM 付きで出してください」と言えれば一番早いのですが、たいていそうもいきません。ダブルクリックで開くのをやめて、Excel 側で読み方を指定します。

Mac だと データ → データ ファイル指定 (Power Query) → テキスト/CSV が一番楽でした。

  1. Excel を開く
  2. データタブ → 左端の「データ ファイル指定 (Power Query)」→「テキスト/CSV」
  3. 参照からファイルを選ぶ
  4. プレビューを確認して「読み込む」

BOM なしの UTF-8 を食わせたところ、プレビューの「元のファイル」は 65001: Unicode (UTF-8)、「区切り記号」は コンマ と、どちらも自動で当たっていました。髙橋商店 も ①番テーブル も化けていません。こちらから指定するものが何もない。

同じドロップダウンに テキストから (レガシ) もあって、こちらは「テキスト ファイル ウィザード」が開きます。ファイル → インポート → CSV ファイルと辿っても同じウィザードでした。入口が 2 つあるだけで中身は同じです。ただ、こちらは自動判定してくれません。

  • 1/3 の画面の「元のファイル:」の既定が Japanese (Mac OS)。これが化ける直接の理由です。Unicode (UTF-8) に変えます
  • 2/3 の画面の区切り文字の既定がタブ。ここを「コンマ」にしないと、文字は読めるのに全部が 1 列に入ります

私は最初この 2 つ目を飛ばして、せっかく綺麗に読めた文字列が丸ごと A 列に詰まったのを見ました。Power Query のほうが確実なのは、この 2 か所を自分で当てにいかなくて済むからです。

Power Query が使えるのは、Microsoft の案内ではバージョン 16.69 以降かつ Microsoft 365 のサブスクリプションという条件付きです。手元の 16.107.2 では問題なく出ました。条件を満たさない環境ではレガシ側が受け皿になります。

Excel にこだわらないなら、LibreOffice は BOM なしの UTF-8 をそのまま読めます。文字コードを何も指定せずに開いて正しく表示されたので、中身を確認したいだけならこれが早いです。

自分が渡す CSV を作るとき

こちらのほうが厄介でした。Excel for Mac で「CSV(コンマ区切り)」を選んで保存すると、UTF-8 では書かれません。保存されたファイルの先頭はこうです。

$ xxd -l 12 out_csv.csv
00000000: 8fa4 9569 96bc 2c90 9497 ca2c            ...i..,....,

BOM はなく、8fa4 9569 96bc が「商品名」。Shift_JIS 系のバイト列です。ではこれを CP932 として読めるかというと、読めません。

$ iconv -f CP932 -t UTF-8 out_csv.csv
商品名,数量,金額
請求書,1,1200
_橋商店,3,4500
iconv: iconv(): Illegal byte sequence

2 か所おかしいところがあります。

1 つは 3 行目の _橋商店。元は 髙橋商店 でした。髙(はしごだか)が消えて、アンダースコアになっています。

もう 1 つは最後で止まっていること。① のところで不正なバイト列だと言われています。Excel が書いた ① は 8540 でしたが、CP932 の ① は 8740 です。別のバイトが入っている。

正体は Mac OS Japanese でした。Foundation の kCFStringEncodingMacJapanese で復号すると、①番テーブル まで含めて最後まで素直に読めます。同じ「Shift_JIS 系」と呼ばれていても、Windows の CP932 とは持っている文字が違うのです。

表現できない文字がどうなるかを、もう少し意地悪な検体で確かめました。

元の値 保存後
𠮷野家 __野家
絵文字😀 絵文字__
森鷗外 森_外

置き換わっているのはファイルの中身だけです。画面上のセルには元の文字が残っているので、保存した本人の目には何も起きていないように見えます。

警告が出ないわけではありません。CSV を開いている間、Excel は本文の上に「データ損失の可能性 このブックをコンマ区切り (.csv) 形式で保存すると、一部の機能が失われる可能性があります」というバーを出しています。ただしこれが言っているのは、書式や複数シートを CSV では持てないという形式一般の話で、髙 が _ になることは何も告げません。読み流してしまう種類の警告です。渡した先で初めて「名前が _ になってます」と言われることになります。

Excel for Mac で人に渡す CSV を作るなら、保存形式は「CSV UTF-8」を選んでください。こちらは先頭に efbbbf が付いた UTF-8 で保存されます。

BOM は誰のために付いているのか

その BOM が、渡す先によっては邪魔になります。人ではなくプログラムに読ませたとき。Python で普通に読むとこうです。

$ python3 -c "
import csv, io
raw = open('utf8_bom.csv', encoding='utf-8').read()
row = next(csv.DictReader(io.StringIO(raw)))
print(list(row.keys()))
print(row['商品名'])
"
['\ufeff商品名', '数量', '金額']
Traceback (most recent call last):
  File "<string>", line 6, in <module>
KeyError: '商品名'

先頭の列名が 商品名 ではなく \ufeff商品名 になっています。\ufeff が BOM で、1 文字目として列名に食い込んだ形です。厄介なのは、この文字が幅を持たないこと。Python は repr で見せてくれますが、print() でそのまま画面に出すと見た目は 商品名 のままです。KeyError を見て「列名は合っているのに」としばらく悩むことになります。

これは読む側の設定ひとつで消えます。encoding='utf-8' を encoding='utf-8-sig' に変えるだけ。sig 付きのほうは BOM があれば読み飛ばし、無ければそのまま読むので、BOM 付きと BOM なしを同じコードで扱えます。手元で両方通したところ、どちらも 商品名 が取れました。

つまり「Excel を取るかプログラムを取るか」という板挟みではないのですね。BOM が働いているのはダブルクリックで開いたときの一瞬だけで、Excel の推測に手がかりを渡している。前の節の Power Query 経路も、ウィザードで文字コードを指定する経路も、BOM があろうとなかろうと同じように開きます。

なので、出す側は BOM を付けておく。受け取る側はそれぞれの流儀で読む。それで両方立ちます。本当に困るのは、受け取り先のコードが utf-8 決め打ちで、しかもそこを直せないときだけです。

おまけ:よく見かけるけれど勧めない対処

まず、Shift_JIS で保存し直すという手。上位に出てくる記事の多くがこれを勧めていて、Excel が Shift_JIS 系を素直に読むのは事実なので、動くことは動きます。ただし片道切符です。CP932 に変換できない文字を並べてみます。

文字 CP932
髙 ① ㈱ Ⅲ 斎 変換できる
鷗(鷗外の鷗) 変換できない
𠮷(つちよし) 変換できない
𩸽(ほっけ) 変換できない
😀 変換できない

人名や店名を含む CSV でこれをやると、変換できなかった文字がその場で失われます。あとから UTF-8 に戻しても帰ってきません。しかも Mac 経由だと 髙 まで落ちる(前の節のとおり)ので、Windows の記事に書いてある「Shift_JIS なら大丈夫」がそのまま通用しない。

もう一つ、UTF-16 で保存し直すという手もよく見ます。試したところ、文字化けは確かに直りました。ただし 商品名,数量,金額 が丸ごと A1 セルに入ります。文字は読めるのに表になっていない、という中途半端なところに着地しました。カンマが区切りとして扱われていないわけですが、なぜそうなるのかまでは確かめていません(タブ区切りの UTF-16 で試していないので、そこは断定を避けておきます)。表として使いたいなら、この手は回り道です。

ついでに、化けているように見えて実は別物のこともあります。引用符の中にカンマや改行が入っている CSV は、Excel はきちんと解釈しました。"カンマ, あり" は 1 セルに収まり、セル内改行も改行のまま残ります。列がずれているだけなら文字コードの問題ではないので、先に区切り文字を疑うほうが早道です。

さいごに

開くときはダブルクリックをやめて Power Query から、渡すときは「CSV UTF-8」で保存。実務で必要なのはこの 2 つだけです。

それにしても、と思うのです。ZIP がファイル名の文字コードを宣言する 1 ビットを後から継ぎ足したように、CSV も BOM という後付けの目印で何とかしのいでいる。どちらも、文字コードが 1 つに決まっていなかった時代に生まれた形式で、後から世界が広がった分のつじつまを端っこで合わせている。髙 が _ に変わったときも、Excel は「一部の機能が失われる可能性があります」としか言いません。嘘はついていないのですが、いま消えたのがその 1 文字だとは教えてくれない。警告の粒度というのは難しいものだな、と思いながら見ていました。

余談ですが、同じ原因でこの記事を書いていて WordPressで 「公開に失敗しました。 データベース内の投稿を更新できませんでした。」とでてハマ りました…

ZIP のファイル名が化ける話は別に書いたので、そちらで困っている方はどうぞ

ZIP を解凍するとファイル名が文字化けする原因と直し方(Mac / Windows)

Mac で圧縮した zip を Windows の人に送ったら「ファイル名が 隲区アよ嶌_2026蟷エ8譛�.txt になってる」と返ってきた。逆に、Windows の人からもらった zip を Mac で開こうとしたら、解凍そのものが Illegal byte sequence で止まった。どちらもよくある話ではないでしょうか。

この 2 つ、症状は正反対に見えますが、原因は同じところにあります。ZIP ファイルの中の、たった 1 ビットです。

検体は macOS 26.5.2(ビルド 25F84)で自分で作って、バイト列まで確かめました。

続きを読む ZIP を解凍するとファイル名が文字化けする原因と直し方(Mac / Windows)

Makefileの「missing separator」エラーを直す:原因はタブとスペースの取り違えがほとんど

make を実行したら

Makefile:2: *** missing separator.  Stop.

と出て止まった。原因はほとんどの場合、レシピ行(コマンドを書く行)の先頭がタブになっていないことです。まずはエラーメッセージにある行番号の行を開いて、行頭がタブかスペースかを確認してください。それで大半は解決します。タブに直したのにまだ消えない、という場合の原因もこの記事に順にまとめてあります。挙動はすべて手元の GNU Make で実際に再現して確認しています。

仕様の詳細は GNU Make 4.4 日本語マニュアル 第5章「ルールのレシピの書き方」 を参照してください。この記事はその実例・トラブルシューティング版です。

まず確認すること

エラーメッセージの Makefile:2: の部分(ファイル名と行番号)を見て、そのMakefileの該当行を開きます。多くの場合、行頭がスペースになっているだけです。

続きを読む Makefileの「missing separator」エラーを直す:原因はタブとスペースの取り違えがほとんど

Makefile関数チートシート:patsubst・wildcard・filter・foreachをコピペで使う

まずは、patsubst の使い方から。

SRCS = main.c util.c parser.c
OBJS = $(patsubst %.c,%.o,$(SRCS))

これで OBJS は main.o util.o parser.o になります。% がワイルドカードで、「.c で終わる各単語を、同じ名前の .o に置き換える」という意味です。この記事は patsubst を軸に、周辺でよく一緒に使う wildcard filter foreach までを逆引きでまとめたチートシートです。挙動はすべて手元の GNU Make で実行して確認しています(macOS標準の 3.81 と Homebrew の 4.4.1。関数の意味はこの範囲で違いはありませんでした)。

網羅的な仕様は GNU Make 4.4 日本語マニュアル 第8章「テキストを変換する関数」 にあります。この記事はその逆引き版です。

patsubst: パターン置換の基本

$(patsubst 検索パターン,置換パターン,対象の文字列) の3引数です。対象の文字列を空白で区切った単語ごとに、検索パターンにマッチしたものだけを置換パターンに差し替えます。

続きを読む Makefile関数チートシート:patsubst・wildcard・filter・foreachをコピペで使う

Codex,Claude Code,Copilotなどの利用状況を確認したい

AI エージェント系の週間の利用状況確認ページ(Weekly Usage Limit Page)を探すときに迷子になるのでまとめておきました。

Codex, Claude Code, GitHub Copilot について調べてます。

Codex (OpenAI)の利用状況

続きを読む Codex,Claude Code,Copilotなどの利用状況を確認したい

Oracle の JOIN の書き方 — 旧記法 (+) と ANSI 構文の対応表

古い Oracle のコードを読んでいると、FROM にテーブルをカンマで並べて WHERE で結合したり、WHERE a.id = b.id(+) のように (+) が付いていたりする SQL に出会います。これは Oracle が ANSI の JOIN 構文に対応する前から使われてきた旧記法で、(+) は Oracle 独自の外部結合演算子です。

結論から言うと、カンマ結合+WHERE は INNER JOIN、(+) は LEFT JOIN / RIGHT JOIN に対応します。この記事では実際の Oracle Database で両者の結果が一致することを確認しながら、書き換えの対応表と、書き換え時に踏みやすい Oracle 固有の癖をまとめます。なお、Oracle 公式マニュアルも新しく書くなら ANSI 構文を推奨しています(後述)。

実測環境は Docker の gvenzl/oracle-free:23-slim-faststart(バナー表記は Oracle AI Database 26ai Free Release 23.26.2.0.0)です。比較用の PostgreSQL 17.10 / MySQL 8.4.10 も Docker で動かしています。サンプルは次の2表です。

続きを読む Oracle の JOIN の書き方 — 旧記法 (+) と ANSI 構文の対応表

INNER JOIN と LEFT JOIN の違い — 結果がどう変わるか実例で確認

INNER JOIN と LEFT JOIN の違いは一言でいうと、相手のいない行を結果に残すかどうかです。INNER JOIN(内部結合)は両方のテーブルに対応する行があるものだけを返し、LEFT JOIN(左外部結合)は左のテーブルの行を全部残して、相手がいない行は右側の列を NULL で埋めます(これを NULL パディングと呼びます)。

この記事では同じデータに両方を実行して結果を見比べたあと、条件を ON に書くか WHERE に書くかで LEFT JOIN の結果が変わる罠と、「LEFT JOIN は遅いのか」という疑問を扱います。実行結果はすべて PostgreSQL 17.10 で実際に確認したもので、ON と WHERE の罠については MySQL 8.4.10 でも同じ結果になることを確認しています。JOIN 全種類のまとめは SQL の JOIN の種類と違いまとめ — INNER/LEFT/RIGHT/FULL/CROSS【2026年更新】 にあります。

サンプルデータ

社員表 emp と部署表 dept を使います。

続きを読む INNER JOIN と LEFT JOIN の違い — 結果がどう変わるか実例で確認

SQL の JOIN は省略できる — INNER/OUTER キーワードとカンマ結合の整理


「JOIN とだけ書いたら INNER JOIN になるのか」「LEFT JOIN と LEFT OUTER JOIN は違うのか」という疑問への答えを先に書くと、どちらもまったく同じものです。INNER と OUTER は書いても書かなくても意味の変わらないキーワードで、省略しても結果は 1 行も変わりません。

この記事では、省略形の対応表と「では実際どこまで省いて書くか」の指針、そして JOIN の省略とよく混同される「カンマ結合(FROM a, b)」がなぜ別物なのかを、実際に動かした結果つきで整理します。動作確認は 2026年7月に PostgreSQL 17.10 / MySQL 8.4.10 / SQLite 3.51.0 と Oracle Database Free(23ai系, 23.26.2.0.0)で行いました。JOIN そのものの種類と結果の違いは SQL の JOIN の種類と違いまとめ — INNER/LEFT/RIGHT/FULL/CROSS【2026年更新】 にまとめているので、そちらもどうぞ。

省略形の対応表

続きを読む SQL の JOIN は省略できる — INNER/OUTER キーワードとカンマ結合の整理

Android の finish() / finishAndRemoveTask() / moveTaskToBack() の違い

Android で「アプリを終了したい」と調べると、finish()、finishAndRemoveTask()、moveTaskToBack(true) が候補に出てきます。名前だけ見ると似ていますが、やっていることは違います。

この記事では、最小 Activity で実際にログを取り、3つの違いを整理します。

比較表

続きを読む Android の finish() / finishAndRemoveTask() / moveTaskToBack() の違い

ImageMagick の xmp:validate とは何か。XMP検証エラーを回避する方法

ImageMagick で JPEG や PNG を処理していると、次のような警告に出会うことがあります。

identify: CorruptImageProfile `bad.jpg' (XMP) @ warning/profile.c/ValidateXMPProfile/2011.

これは画像に埋め込まれた XMP メタデータを ImageMagick が XML として読もうとして、壊れていると判断したときの警告です。画像のピクセル変換そのものが失敗しているとは限りません。

この記事では、壊れた XMP 入りの JPEG を手元で作って、xmp:validate を付けたときに何が起きるかを確認します。

xmp:validate は何をしているのか

xmp:validate は ImageMagick の -define で指定する設定です。

公式の defines ページでは、xmp:validate={true,false} は「画像に埋め込まれた XMP プロファイルを検証する」と説明されています。

XMP は、ざっくり言うと画像に入る XML 形式のメタデータです。撮影・編集ソフト・権利情報・説明文などが入ることがあります。ImageMagick 側では、XML delegate が有効なビルドだと、この XMP を XML として読めるか確認できます。

手元の ImageMagick 7.1.2-27 では、xmp:validate=true を明示したときに CorruptImageProfile ... (XMP) の警告を確認しました。公式説明には「デフォルトで検証」とありますが、少なくともこの環境では、素の identify や変換では警告が出ませんでした。バージョンやビルド設定で挙動が違う可能性があるので、まず自分の環境で確認するのがよいです。

確認環境は以下です。

Version: ImageMagick 7.1.2-27 Q16-HDRI aarch64 e4c2b403b:20260705 https://imagemagick.org
Features: Cipher DPC HDRI Modules
Delegates (built-in): bzlib freetype heic jng jpeg lcms ltdl lzma png tiff webp xml zlib zstd

壊れた XMP 入り JPEG を作る

まず、わざと XML として壊れた XMP ファイルを作ります。

printf '\xff\xfe\x00\x00not xml\n' > bad.xmp
magick -size 32x32 xc:white base.jpg

普通に -profile bad.xmp すると環境によっては追加時点で警告されるので、ここでは xmp:validate=false を付けて、壊れた XMP を持つ JPEG を作ります。

magick base.jpg -define xmp:validate=false -profile bad.xmp bad.jpg

XMP プロファイルが入っていることは identify -verbose で確認できます。

magick identify -verbose bad.jpg 2>/dev/null | grep -Ei 'profiles|profile-xmp'

出力:

  Profiles:
    Profile-xmp: 12 bytes

xmp:validate=true で警告を再現する

xmp:validate=true を付けて identify します。

magick identify -define xmp:validate=true bad.jpg
echo $?

手元ではこうなりました。

bad.jpg JPEG 32x32 32x32+0+0 8-bit Grayscale Gray 256c 210B 0.000u 0:00.001
identify: CorruptImageProfile `bad.jpg' (XMP) @ warning/profile.c/ValidateXMPProfile/2011.
0

ここで大事なのは、終了コードが 0 のままだったことです。つまり、少なくともこのケースでは「警告は出るが、コマンドとしては成功」です。スクリプトが stderr の文字列を見て失敗扱いしている場合は別ですが、終了コードだけを見る処理なら失敗にはなりません。

警告だけ消すなら -quiet

ログに警告を出したくないだけなら、-quiet で警告は消えました。

magick identify -quiet -define xmp:validate=true bad.jpg
echo $?

出力:

bad.jpg JPEG 32x32 32x32+0+0 8-bit Grayscale Gray 256c 210B 0.000u 0:00.001
0

ただし、これは警告を黙らせるだけです。壊れた XMP は画像内に残ります。

検証を止めるなら xmp:validate=false

XMP の検証自体を止めるなら、入力ファイルより前に -define xmp:validate=false を置きます。

magick identify -define xmp:validate=false bad.jpg
echo $?

出力:

bad.jpg JPEG 32x32 32x32+0+0 8-bit Grayscale Gray 256c 210B 0.000u 0:00.000
0

変換でも同じ考え方です。

magick -define xmp:validate=false bad.jpg out.png

-define は入力を読む前に効かせたいので、迷ったら入力ファイル名より前に置くのが安全です。

XMP を消すなら +profile xmp

壊れた XMP が不要なら、検証を止めて読み込み、そのあとで XMP プロファイルだけ削除します。

magick -define xmp:validate=false bad.jpg +profile xmp clean-no-xmp.jpg
echo $?

出力:

0

削除後のファイルを確認します。

magick identify -verbose clean-no-xmp.jpg 2>/dev/null | grep -Ei 'profiles|profile-xmp'

出力は空でした。さらに、削除後のファイルは xmp:validate=true で読んでも警告が出ません。

magick identify -define xmp:validate=true clean-no-xmp.jpg
echo $?

出力:

clean-no-xmp.jpg JPEG 32x32 32x32+0+0 8-bit Grayscale Gray 256c 165B 0.000u 0:00.000
0

すべてのメタデータを消してよいなら -strip

XMP だけでなく、EXIF や ICC などのプロファイル、コメント類も落としてよいなら -strip が使えます。

magick -define xmp:validate=false bad.jpg -strip clean-strip.jpg
echo $?

出力:

0

-strip は画像を軽くしたいときには便利ですが、色管理の ICC プロファイルや撮影情報も落ちます。Web用サムネイルなら問題ないことが多い一方、印刷・写真管理・権利情報を残したい用途では雑に使わない方がよいです。

どれを使うべきか

目的別に分けると、こうです。

目的コマンド例注意
警告をログに出したくないだけmagick identify -quiet -define xmp:validate=true bad.jpgXMP は残る
XMP 検証をスキップしたいmagick -define xmp:validate=false input.jpg output.png壊れた XMP を温存する場合がある
XMP だけ消したいmagick -define xmp:validate=false input.jpg +profile xmp output.jpgXMP 内の説明・権利情報も消える
全メタデータを消してよいmagick -define xmp:validate=false input.jpg -strip output.jpgEXIF/ICC/コメントも消える

Webアプリの画像変換で「ユーザー投稿画像を縮小して表示するだけ」なら、-define xmp:validate=false と -strip の組み合わせで済むことが多いです。逆に、写真のメタデータや色プロファイルを大事にする処理では、-strip ではなく +profile xmp のように削除対象を絞った方が安全です。

さいごに

xmp:validate は、画像のピクセルではなく XMP メタデータの検証に関わる設定です。CorruptImageProfile ... (XMP) が出ても、まずは終了コード、出力ファイル、XMP が必要かどうかを分けて見た方がよいです。

今回の手元検証では、警告が出ても終了コードは 0、-quiet は警告を隠すだけ、xmp:validate=false は検証を止める、+profile xmp と -strip はメタデータを実際に削除する、という違いが確認できました。

関連: