コマンドラインでplistを操作（データ追加・編集・削除）


## 概要

plutilコマンドを使うと、プロパティリスト形式のファイル（.plist）をCUIから操作することができます。日本語の解説が無くて寂しい思いをしたのでまとめました...。コマンドラインからplistのレコードの書き換えたい貴方に、届け！この想い！



動作確認環境：Mac OS X 10.9.3 Marvericks / Xcode 5.1.1

## データを挿入する

```Bash
$ plutil -insert <キー名> <-型> <値> <plistファイルパス>
```

指定できる型と値は以下の通り。

| 型       |  値 |
|:---------|------------:|
| -bool    | YES, NO, true, false |
| -integer | 64ビット整数 |
| -float   | 64ビット浮動小数 |
| -string  | UTF8エンコード文字列 |
| -date    | XML形式の日付 |
| -data    | base-64エンコード文字列 |
| -xml     | XML形式。複数の値・階層化された値の挿入 |
| -json    | JSON形式。複数の値・階層化された値の挿入 |

例）

```Bash
$ plutil -insert 'myBoolKey' -bool YES info_insert.plist

$ plutil -insert 'myIntegerKey' -integer 123 info_insert.plist

$ plutil -insert 'myFloatKey' -integer 1.2 info_insert.plist

$ plutil -insert 'myStringKey' -string 'myStringValue' info_insert.plist

$ plutil -insert 'myDateKey' -date '<date>1999-05-31T13:20:00.000-05:00</date>' info_insert.plist
# date型だけパースエラーになっちゃう...なんで？

$ plutil -insert 'myDataKey' -data 'bXkgZGF0YSB2YWx1ZSBvZiBiYXNlIDY0IGZvcm1hdA==' info_insert.plist

$ plutil -insert 'myKeyArrayXml' -xml '<array><string>item0String</string><real>1</real><date>2014-07-06T04:38:39Z</date></array>' info_insert.plist

$ plutil -insert 'myKeyArrayJson' -json '["item0String",1,"2014-07-06T04:38:39Z"]' info_insert.plist

$ plutil -insert 'myKeyDictionaryJson' -json '{"item0Key:":"item0String","item1Key":1,"item2Key":"2014-07-06T04:38:39Z"}' info_insert.plist
```

## データを置換する

```Bash
$ plutil -replace <キー名> <-型> <値> <plistファイルパス>
```

例）

```Bash
$ plutil -replace 'myBoolKey' -bool YES info_replace.plist

$ plutil -replace 'myIntegerKey' -integer 123 info_replace.plist

$ plutil -replace 'myFloatKey' -integer 1.2 info_replace.plist

$ plutil -replace 'myStringKey' -string 'myStringValue' info_replace.plist

$ plutil -replace 'myDateKey' -date '<date>1999-05-31T13:20:00.000-05:00</date>' info_replace.plist
# date型だけパースエラーになっちゃう...なんで？

$ plutil -replace 'myDataKey' -data 'bXkgZGF0YSB2YWx1ZSBvZiBiYXNlIDY0IGZvcm1hdA==' info_replace.plist

$ plutil -replace 'myKeyArrayXml' -xml '<array><string>item0String</string><real>1</real><date>2014-07-06T04:38:39Z</date></array>' info_replace.plist

$ plutil -replace 'myKeyArrayJson' -json '["item0String",1,"2014-07-06T04:38:39Z"]' info_replace.plist

$ plutil -replace 'myKeyDictionaryJson' -json '{"item0Key:":"item0String","item1Key":1,"item2Key":"2014-07-06T04:38:39Z"}' info_replace.plist
```

## データを削除する

```Bash
$ plutil -remove <キー名> <plistファイルパス>
```

例）

```Bash
$ plutil -remove 'myBoolKey' info_remove.plist

$ plutil -remove 'myIntegerKey' info_remove.plist

$ plutil -remove 'myFloatKey' info_remove.plist

$ plutil -remove 'myStringKey' info_remove.plist

$ plutil -remove 'myDateKey' info_remove.xml

$ plutil -remove 'myDataKey' info_remove.plist

$ plutil -remove 'myKeyArrayXml' info_remove.plist

$ plutil -remove 'myKeyArrayJson' info_remove.plist

$ plutil -remove 'myKeyDictionaryJson' info_remove.plist
```

## plistの文法チェック

```Bash
$ plutil -lint <plistファイル>
```

例）正しいplist

```Bash
$ plutil -lint info.plist
info.plist: OK
```

例）正しくないplist　※XMLの閉じタグがないよ！

```Bash
$ plutil -lint info.plist
info.plist: Encountered unexpected character < on line 7 while looking for close tag
# ちゃんとエラー箇所を教えてくれる
```


## plistのフォーマット変換

```Bash
$ plutil -convert <フォーマット> <plistファイルパス>
```
**※注意：指定したplistファイルは上書きされるので気を付けること**
上書きされたくない場合は、後述の`-o`オプションを使用する。

指定できるフォーマットは以下の通り。

| フォーマット |  記述        |
|:-----------|------------:|
| XML        | -xml1     |
| JSON       | -json     |
| バイナリ     | -binary1 |


例）XMLに変換

```Bash
$ plutil -convert xml1 info.plist
```

例）JSONに変換

```Bash
$ plutil -convert json info.plist 
```

例）JSONに変換 `-r` オプションを指定すると、読みやすく整形してくれる。

```Bash
$ plutil -convert json -r info.plist 
```

例）バイナリに変換

```Bash
$ plutil -convert binary1 info.plist
```

## plistのフォーマット変換（新規生成）

```Bash
$ plutil -convert <フォーマット> <変換元plistファイルパス> -o <新規plistファイルパス>
```

例）XMLに変換しつつ、`info_new.plist`として新規生成する

```Bash
$ plutil -convert xml1 info.plist -o info_new.plist
```

## plistのフォーマット変換（拡張子を指定して新規生成）

`-e <拡張子>` オプションで、変換後のファイルの拡張子を指定しつつ、新規ファイルとして生成できる。

例）info.plist から info.xml を生成

```Bash
$ plutil -convert xml1 -e xml info.plist
# 新たにinfo.xmlが生成される
```

## コマンド成功時のメッセージを出力しない

`-s` オプションを指定する。

例）plistの文法チェックで、コマンド成功時のメッセージ`info.plist: OK`を出力しない

```Bash
$ plutil -lint -s info.plist
# 何も出力されない
```

## plistをコマンドライン上に出力する

`-p` オプションを指定する。
なお、単純なファイル出力ではなく、読みやすく整形された出力になる（現時点ではJSON出力で固定。例えばXML形式のplistを指定してもJSON形式で出力される）。

例）

```Bash
$ plutil -p info.plist
{
  "CFBundleName" => "${PRODUCT_NAME}"
  "CFBundleIdentifier" => "com.example.${PRODUCT_NAME:rfc1034identifier}"
  "CFBundleInfoDictionaryVersion" => "6.0"
  "UIMainStoryboardFile" => "Main"
  "CFBundleVersion" => "1.0"
  "UIRequiredDeviceCapabilities" => [
    0 => "armv7"
  ]
  "CFBundleExecutable" => "${EXECUTABLE_NAME}"
  "LSRequiresIPhoneOS" => 1
  "UISupportedInterfaceOrientations" => [
    0 => "UIInterfaceOrientationPortrait"
    1 => "UIInterfaceOrientationLandscapeLeft"
    2 => "UIInterfaceOrientationLandscapeRight"
  ]
  "CFBundleDisplayName" => "${PRODUCT_NAME}"
  "CFBundlePackageType" => "APPL"
  "CFBundleSignature" => "????"
  "CFBundleDevelopmentRegion" => "en"
  "CFBundleShortVersionString" => "1.0"
}
```

## 任意のキーの値を抜き出す

```Bash
$ plutil -extract <キー名> <フォーマット> <plistファイルパス>
```

例）キー：`CFBundleIdentifier` の値を抜き出して、XMLに変換しつつ、`CFBundleIdentifier.xml` として新規生成する

```Bash
$ plutil -extract 'CFBundleIdentifier' xml1 info.plist -o CFBundleIdentifier.xml
plutil -extract 'CFBundleIdentifier' xml1 info.plist -o -
```

新規生成された CFBundleIdentifier.xml を開くと、値のみが抜き出されている（キーは抜き出されていない）

```xml
<?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">
<string>com.example.${PRODUCT_NAME:rfc1034identifier}</string>
</plist>
```

## plutilコマンドのヘルプ

```Bash
$ plutil -help
plutil: [command_option] [other_options] file...
The file '-' means stdin
Command options are (-lint is the default):
 -help                         show this message and exit
 -lint                         check the property list files for syntax errors
 -convert fmt                  rewrite property list files in format
                               fmt is one of: xml1 binary1 json
 -insert keypath -type value   insert a value into the property list before writing it out
                               keypath is a key-value coding key path, with one extension:
                               a numerical path component applied to an array will act on the object at that index in the array
                               or insert it into the array if the numerical path component is the last one in the key path
                               type is one of: bool, integer, float, date, string, data, xml, json
                               -bool: YES if passed "YES" or "true", otherwise NO
                               -integer: any valid 64 bit integer
                               -float: any valid 64 bit float
                               -string: UTF8 encoded string
                               -date: a date in XML property list format, not supported if outputting JSON
                               -data: a base-64 encoded string
                               -xml: an XML property list, useful for inserting compound values
                               -json: a JSON fragment, useful for inserting compound values
                               value YES, NO, a number, a date, or a base-64 encoded blob of data
 -replace keypath -type value  same as -insert, but it will overwrite an existing value
 -remove keypath               removes the value at 'keypath' from the property list before writing it out
 -extract keypath fmt          outputs the value at 'keypath' in the property list as a new plist of type 'fmt'
                               fmt is one of: xml1 binary1 json
 -p                            print property list in a human-readable fashion
                               (not for machine parsing! this 'format' is not stable)
There are some additional optional arguments that apply to the -convert, -insert, -remove, -replace, and -extract verbs:
 -s                            be silent on success
 -o path                       specify alternate file path name for result;
                               the -o option is used with -convert, and is only
                               useful with one file argument (last file overwrites);
                               the path '-' means stdout
 -e extension                  specify alternate extension for converted files
 -r                            if writing JSON, output in human-readable form
 --                            specifies that all further arguments are file names
```

おしまい。