PlistBuddyを使うと、Info.plistなどのplistの値をコマンドで読み書きできる。-cでコマンドを渡す。

$ /usr/libexec/PlistBuddy -c "Print :CFBundleShortVersionString" Info.plist
1.2.3
$ /usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString 1.2.4" Info.plist

PlistBuddyは/usr/libexec/にあり、PATHに含まれない。フルパスで実行する。

実行例はmacOS 27.0.1のもの。

コマンドの形式 (-c)

PlistBuddyの書式は次のとおりである。

$ /usr/libexec/PlistBuddy -c "[コマンド]" [plistファイル]

-cを複数指定すると、順番に実行される。-cを指定しないと、対話モードになる。

主なコマンドは次のとおりである。

コマンド内容
Print [キー]値を表示する。キーを省略すると全体を表示する
Set [キー] [値]既存のキーの値を書き換える
Add [キー] [型] [値]キーを追加する
Delete [キー]キーを削除する
Copy [コピー元のキー] [コピー先のキー]値をコピーする
Merge [plistファイル] [キー]別のplistの内容を追加する
Import [キー] [ファイル]ファイルの内容をdata型の値として設定する
Clear [型]全体を空にして、ルートの型を指定して作り直す

キーは、コロン区切りで階層を指定する。配列の要素は、0から始まる番号で指定する。

:CFBundleShortVersionString
:CFBundleDocumentTypes:0:CFBundleTypeExtensions:1

先頭のコロンは省略しても動作する。

値を読む (Print)

Printにキーを指定すると、値が表示される。

$ /usr/libexec/PlistBuddy -c "Print :CFBundleShortVersionString" Info.plist
1.2.3
$ /usr/libexec/PlistBuddy -c "Print :LSUIElement" Info.plist
true
$ /usr/libexec/PlistBuddy -c "Print :Ratio" Info.plist
1.500000

real型は、小数点以下が6桁で表示される。

階層の深い値は、コロンでたどる。

$ /usr/libexec/PlistBuddy -c "Print :CFBundleDocumentTypes:0:CFBundleTypeExtensions:1" Info.plist
md

配列や辞書を指定すると、中身がまとめて表示される。

$ /usr/libexec/PlistBuddy -c "Print :CFBundleDocumentTypes:0:CFBundleTypeExtensions" Info.plist
Array {
    txt
    md
}

キーを省略すると、plist全体が表示される。辞書のキーの順番は、ファイルに書かれた順番と一致しない。

存在しないキーや範囲外の番号を指定すると、エラーメッセージが表示され、終了コードが1になる。

$ /usr/libexec/PlistBuddy -c "Print :NoSuch" Info.plist
Print: Entry, ":NoSuch", Does Not Exist
$ echo $?
1

インストール済みのアプリの設定を確認する

アプリのContents/Info.plistを指定すると、インストール済みのアプリの設定を確認できる。たとえば、Sparkleのアップデート配信先のSUFeedURLを確認できる。

$ /usr/libexec/PlistBuddy -c "Print :SUFeedURL" /Applications/[アプリ名].app/Contents/Info.plist
https://example.com/appcast.xml

XcodeのプロジェクトにあるInfo.plistは、$(MARKETING_VERSION)のようなビルド設定の変数が、そのまま文字列として表示される。

$ /usr/libexec/PlistBuddy -c "Print :CFBundleShortVersionString" Info.plist
$(MARKETING_VERSION)

XML形式で出力する (-x)

-xを付けると、結果がXMLのplist形式で出力される。

$ /usr/libexec/PlistBuddy -x -c "Print :CFBundleDocumentTypes:0:CFBundleTypeExtensions" Info.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
	<string>txt</string>
	<string>md</string>
</array>
</plist>

値を書き換える (Set)

Setは、既存のキーの値を書き換える。

$ /usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString 2.0.0" Info.plist
$ /usr/libexec/PlistBuddy -c "Print :CFBundleShortVersionString" Info.plist
2.0.0

空白を含む値は、引用符で囲む。

$ /usr/libexec/PlistBuddy -c 'Set :CFBundleIdentifier "com.example.my app"' Info.plist

存在しないキーを指定すると、エラーになり終了コードが1になる。

$ /usr/libexec/PlistBuddy -c "Set :NoSuch x" Info.plist
Set: Entry, ":NoSuch", Does Not Exist
$ echo $?
1

配列や辞書にはSetできない。

$ /usr/libexec/PlistBuddy -c "Set :CFBundleDocumentTypes x" Info.plist
Set: Cannot Perform Set On Containers

Setは、既存の値の型を変えない。string型のキーに100を設定しても、string型のままである。

不正な値でも終了コードが0になる

型に合わない値をSetしたときは、エラーが出ても終了コードが0になる場合がある。

整数型のキーに整数ではない値を設定すると、エラーメッセージが表示される。値は書き換わらず、終了コードは0である。

$ /usr/libexec/PlistBuddy -c "Set :Count abc" Info.plist
Unrecognized Integer Format
$ echo $?
0
$ /usr/libexec/PlistBuddy -c "Print :Count" Info.plist
3

bool型のキーに、true・yes・1などの真を表す値以外(abcなど)を設定すると、エラーにならず、falseになる。

$ /usr/libexec/PlistBuddy -c "Set :LSUIElement abc" Info.plist
$ /usr/libexec/PlistBuddy -c "Print :LSUIElement" Info.plist
false

書き込み権限のないファイルへのSetも、エラーメッセージが表示されるだけで、終了コードは0になる。

$ /usr/libexec/PlistBuddy -c "Set :CFBundleVersion 1" Info.plist
Error Opening Destination: Info.plist [Permission denied]
$ echo $?
0

CIなどで確実に書き換えたいときは、Setの後にPrintで値を確認する。

$ /usr/libexec/PlistBuddy -c "Set :CFBundleVersion $BUILD_NUMBER" Info.plist
$ [ "$(/usr/libexec/PlistBuddy -c "Print :CFBundleVersion" Info.plist)" = "$BUILD_NUMBER" ] || exit 1

キーを追加する (Add)

Addは、キーと型と値を指定して、キーを追加する。

$ /usr/libexec/PlistBuddy -c "Add :NewKey string hello" Info.plist
$ /usr/libexec/PlistBuddy -c "Print :NewKey" Info.plist
hello

指定できる型は次のとおりである。

型値の例
stringhello
booltrue
integer7
real0.5
date"Thu Oct 8 12:00:00 JST 2026"(dateコマンドの出力形式)
dataabc
array値は指定しない
dict値は指定しない

date型にISO 8601形式(2026-10-08T00:00:00Z)を指定すると、Unrecognized Date Formatと表示され、キーは追加されない。終了コードは0である。

値を省略したstring型は、空文字列になる。

既存のキーを追加しようとすると、エラーになり終了コードが1になる。

$ /usr/libexec/PlistBuddy -c "Add :CFBundleVersion string 1" Info.plist
Add: ":CFBundleVersion" Entry Already Exists
$ echo $?
1

階層の途中に追加する

親のキーが存在しなくても、Addで階層の深いキーを追加すると、途中の辞書が自動で作られる。

$ /usr/libexec/PlistBuddy -c "Add :NoParent:k string v" Info.plist
$ /usr/libexec/PlistBuddy -c "Print :NoParent" Info.plist
Dict {
    k = v
}

配列に要素を追加する

配列のキーの末尾にコロンを付けると、配列の末尾に要素が追加される。

$ /usr/libexec/PlistBuddy -c "Add :CFBundleDocumentTypes:0:CFBundleTypeExtensions: string rtf" Info.plist
$ /usr/libexec/PlistBuddy -c "Print :CFBundleDocumentTypes:0:CFBundleTypeExtensions" Info.plist
Array {
    txt
    md
    rtf
}

番号を指定すると、その位置に要素が挿入される。

$ /usr/libexec/PlistBuddy -c "Add :CFBundleDocumentTypes:0:CFBundleTypeExtensions:0 string first" Info.plist
$ /usr/libexec/PlistBuddy -c "Print :CFBundleDocumentTypes:0:CFBundleTypeExtensions" Info.plist
Array {
    first
    txt
    md
}

キーを削除・コピー・結合する

削除する (Delete)

Deleteは、キーを削除する。配列の要素は、番号で指定する。

$ /usr/libexec/PlistBuddy -c "Delete :SUFeedURL" Info.plist
$ /usr/libexec/PlistBuddy -c "Delete :CFBundleDocumentTypes:0:CFBundleTypeExtensions:0" Info.plist

存在しないキーを指定すると、エラーになり終了コードが1になる。

コピーする (Copy)

Copyは、値をコピーする。辞書も、中身ごとコピーされる。

$ /usr/libexec/PlistBuddy -c "Copy :CFBundleShortVersionString :CopiedVersion" Info.plist
$ /usr/libexec/PlistBuddy -c "Copy :CFBundleDocumentTypes:0 :Doc0" Info.plist

コピー先のキーが存在すると、エラーになり終了コードが1になる。

$ /usr/libexec/PlistBuddy -c "Copy :CFBundleShortVersionString :CFBundleVersion" Info.plist
Copy: ":CFBundleVersion" Entry Already Exists

別のplistを結合する (Merge)

Mergeは、別のplistの内容を追加する。

$ /usr/libexec/PlistBuddy -c "Merge [追加するplistファイル]" Info.plist

キーが重複していると、重複したキーはスキップされ、既存の値が残る。スキップしても終了コードは0である。

$ /usr/libexec/PlistBuddy -c "Merge [追加するplistファイル]" Info.plist
Duplicate Entry Was Skipped: CFBundleVersion

キーを指定すると、そのキーの下に結合される。

$ /usr/libexec/PlistBuddy -c "Add :Sub dict" -c "Merge [追加するplistファイル] :Sub" Info.plist

ファイルの内容を取り込む (Import)

Importは、ファイルの内容を、data型の値として設定する。

$ /usr/libexec/PlistBuddy -c "Import :Blob [ファイル]" Info.plist

存在しないファイルを指定すると、エラーになり終了コードが1になる。

全体を作り直す (Clear)

Clear [型]は、全体を空にして、ルートの型を指定して作り直す。

$ /usr/libexec/PlistBuddy -c "Clear dict" Info.plist
Initializing Plist...

保存の仕組み

-cでは自動で保存される

-cで実行した変更は、Saveを実行しなくてもファイルに保存される。-cにExitを指定しても、変更は破棄されない。

-cを複数指定したとき、途中のコマンドがエラーになっても、後ろのコマンドは実行される。終了コードは1になる。

$ /usr/libexec/PlistBuddy -c "Set :CFBundleVersion 1" -c "Set :NoSuch x" -c "Set :CFBundleShortVersionString 9.9.9" Info.plist
Set: Entry, ":NoSuch", Does Not Exist
$ echo $?
1
$ /usr/libexec/PlistBuddy -c "Print :CFBundleVersion" Info.plist
1
$ /usr/libexec/PlistBuddy -c "Print :CFBundleShortVersionString" Info.plist
9.9.9

対話モードではSaveが必要

-cを指定しないと、対話モードで起動し、Command:のプロンプトが表示される。対話モードでは、Saveを実行するまで、変更はファイルに保存されない。

$ /usr/libexec/PlistBuddy Info.plist
Command: Set :CFBundleVersion 6
Command: Save
Saving...
Command: Exit

Exitは、保存せずに終了する。Revertは、保存済みの状態へ戻す。

Command: Set :CFBundleVersion 7
Command: Revert
Reverting to last saved state...

標準入力が終了した場合も、Saveを実行していない変更は破棄される。

保存すると形式とキーの順番が変わる

PlistBuddyで保存すると、plist全体が書き直される。

  • バイナリ形式のplistは、XML形式に変わる
  • キーが、アルファベット順に並べ替えられる
  • 値を変更しないSetでも、並べ替えは行われる

plutil -replaceでも、XML形式のplistは、キーがアルファベット順に並べ替えられる。

キーがすでにアルファベット順に並んでいるplistは、PlistBuddyで値を書き換えても、差分には書き換えた値の行だけが表示される。並んでいないplistは、並べ替えによる変更も差分に含まれる。

JSON形式のplistは、PlistBuddyでは読み込めない。

$ /usr/libexec/PlistBuddy -c "Print :a" [JSON形式のplist]
Unexpected character { at line 1
Error Reading File: [JSON形式のplist]
$ echo $?
1

存在しないファイルを指定する

存在しないファイルにAddすると、ファイルが新規に作られる。ルートは辞書になる。

$ /usr/libexec/PlistBuddy -c "Add :k string v" new.plist
File Doesn't Exist, Will Create: new.plist
$ plutil -p new.plist
{
  "k" => "v"
}

ルートを配列にしたいときは、Clear arrayで作り直す。

$ /usr/libexec/PlistBuddy -c "Clear array" -c "Add :0 string a" new.plist

Printだけを実行したときは、ファイルは作られない。

キー名の特殊文字

キー名にコロンが含まれるときは、バックスラッシュでエスケープする。

$ /usr/libexec/PlistBuddy -c 'Print :a\:b' c.plist
x

キー名に空白が含まれるときは、キーを引用符で囲む。

$ /usr/libexec/PlistBuddy -c 'Print ":my key"' s.plist
x

オプション

-cと-x以外のオプションは次のとおりである。

オプション内容
-lシンボリックリンクをたどらない。リンクを指定するとエラーになる
-hコマンドの詳細なヘルプを表示する

plutilとの使い分け

plistを操作するplutilと比べた違いは次のとおりである。

項目PlistBuddyplutil
実行ファイル/usr/libexec/PlistBuddy(PATH外)/usr/bin/plutil
キーの指定:A:B:0A.B.0
型の指定Addで型を指定する。Setは既存の型に合わせる-stringなどで毎回指定する
コピー・結合・取り込みCopy・Merge・Import専用のコマンドはない
保存時の形式バイナリはXMLに変わる。JSONは読めない元の形式を保つ
書き込めないときの終了コード01

plutilは、元の形式を保って保存し、書き込みの失敗を終了コードで返す。plutil -insertでも、配列の途中に要素を挿入できる。一方、PlistBuddyには、辞書を丸ごとコピーするCopy、別のplistを結合するMerge、ファイルを取り込むImportがある。値の書き換えが中心ならplutilを使う。コピーや結合が必要ならPlistBuddyを使う。

参考: 【plutil】コマンドの使い方まとめ

参考: 【GitHub Actions】CIでだけ署名設定をDeveloper IDに切り替える