← ./articles-ja

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をまたぐより、ずっと壊れにくくなります。

参考