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
指定できる型は次のとおりである。
| 型 | 値の例 |
|---|---|
string | hello |
bool | true |
integer | 7 |
real | 0.5 |
date | "Thu Oct 8 12:00:00 JST 2026"(dateコマンドの出力形式) |
data | abc |
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と比べた違いは次のとおりである。
| 項目 | PlistBuddy | plutil |
|---|---|---|
| 実行ファイル | /usr/libexec/PlistBuddy(PATH外) | /usr/bin/plutil |
| キーの指定 | :A:B:0 | A.B.0 |
| 型の指定 | Addで型を指定する。Setは既存の型に合わせる | -stringなどで毎回指定する |
| コピー・結合・取り込み | Copy・Merge・Import | 専用のコマンドはない |
| 保存時の形式 | バイナリはXMLに変わる。JSONは読めない | 元の形式を保つ |
| 書き込めないときの終了コード | 0 | 1 |
plutilは、元の形式を保って保存し、書き込みの失敗を終了コードで返す。plutil -insertでも、配列の途中に要素を挿入できる。一方、PlistBuddyには、辞書を丸ごとコピーするCopy、別のplistを結合するMerge、ファイルを取り込むImportがある。値の書き換えが中心ならplutilを使う。コピーや結合が必要ならPlistBuddyを使う。
参考: 【GitHub Actions】CIでだけ署名設定をDeveloper IDに切り替える
