system()」というスレッドがあったので、Windows上でVimからプログラムに引数を渡したい時の注意点を簡単にまとめて返信したので、日本語でも書いてみます。VimからWindowsプログラムに引数を渡すにはいくつか難しい点があります。複数の引数や特殊な文字*1を渡す場合等にハマります。Vim側の問題Windowsでは、'shellslash'オプションがオンの時、shellescape()は文字列をシングルクォートで囲って返します。cmd.exeはダブルクォートを使うので、シングルクォートで囲っても単純にシングルクォートがそのまま渡されてしまいます。私はWindowsかつ'shellslash'オプションがオンの時でも期待通りに動くshellescape()関数を独自実装して使っています。GitHubWindows側の問題Windowsは複数の引数をWin32APIレベルでサポートしていません。いう事かと言うと、新しいプロセスを開始するCreateProcess()関数は、プログラム名と引数を含めた単一のコマンドライン文字列を渡すよう設計されています。test.txt"という単一の文字列を渡します。いった設計なので、Windows上で実行されるプログラムは引数をパースしなければなりません。普通この処理を書く必要に駆られる事はありません。ここで2つ問題があります。スタートアップルーチンを独自の解釈で実装しているプログラムがあるcmd.exeとCreateProcess()のパース処理のソースコードがクローズドな事スタートアップルーチンを独自の解釈で実装しているプログラムがある例えば、cygwinに依存した*3実行ファイルはグロブ文字("*")といったUNIX系で使われる特殊な文字を独自で解釈します。cmd.exeとCreateProcess()のパース処理のソースコードがクローズドな事クローズドなので正確な処理を確認する事ができません。今回はVimのsystem()関数に関連するスレッドのため、cmd.exe上からプログラムを起動する前提で話します。この場合、3つ疑うべき箇所があります。それは起動順で言うと以下の3つです。cmd.exeCreateProcess()スタートアップルーチン流れとしては以下のような流れになります。[プログラムが引数にアクセスする]この3つの箇所のどこかで間違った解釈がなされているはずです。疑う事しかできない場合もあります。等の対策が立てられる...場合もあります(どうしようもない場合もある)。結論VimからWindowsプログラムに引数を渡すのは難しい。「大体合ってる」位の方法しかWindows開発者には選択肢がない。永遠に未完成cmd.exeの挙動について詳細に調査した大掛かりな記事*1:スペース、^等、cmd.exeにとっての特殊な文字もあれば、cygwinの実行ファイルの場合*等の文字も独自の解釈がなされる場合もあります*2:C言語ではスタートアップルーチンはmain()関数の前に呼び出されます。ほしいタイトルは前記事からの流用。