Git BashでWindowsパス入りJSONを書く時はinline node -eとprintfを避ける
Git BashからJSONを書くのは簡単そうに見えます。
しかしJSONの中にWindowsパスが入ると、バックスラッシュが壊れることがあります。
{ "path": "<windows-path>\\tools\\cache\\**" }
このつもりが、途中で \t がtab文字として解釈され、別の文字列になることがあります。
壊れやすい例
次のようなinline commandは避けます。
node -e 'const x = { path: "<windows-path>\\tools\\cache\\**" }; console.log(JSON.stringify(x))'
また、printf で直接JSONを書くのも危険です。
printf '{"path":"<windows-path>\\tools\\cache\\**"}' > config.json
shell、引用符、Node、JSONのエスケープが重なり、意図したバックスラッシュが保たれないことがあります。
script fileに逃がす
安全なのは、JSON生成処理を .js ファイルへ書くことです。
const fs = require("fs");
const config = {
path: "<windows-path>\\tools\\cache\\**",
};
fs.writeFileSync("config.json", JSON.stringify(config, null, 2));
実行はシンプルです。
node write-config.js
shellはファイル名をNodeへ渡すだけなので、JSON文字列の中身を再解釈しません。
PowerShellならConvertTo-Json
PowerShell上で作るなら、手書きJSONではなくobjectから変換します。
@{
path = "<windows-path>\tools\cache\**"
} | ConvertTo-Json | Set-Content -Encoding utf8 config.json
これならJSONのquoteやescapeを自分で組み立てる必要がありません。
チェックリスト
次を含むJSONは、inline one-linerではなくscript fileで作ります。
- Windows path
- backslash
- glob pattern
- regular expression
- nested quote
まとめ
Git BashでWindowsパス入りJSONが壊れるなら、エスケープを増やして粘るより、script fileに逃がすほうが安定します。
.js や .ps1 に処理を書き、shellにはファイル名だけ渡してください。複数のparserをまたぐより、ずっと壊れにくくなります。