echo foo | set /p x= で x は設定できない
[Windows] コマンドプロンプトで文字列入出力のTipsでは改行なしのメッセージを set /p を使って出力した。>set /p x=hello<nul & echo world hello world >
これを使って、別のコマンドの出力をパイプを通して変数に格納できないかなと思ってやってみたら、できなかった。
>echo foo | set /p x= >set x 環境変数 x が定義されていません >
うーん、なんでうまくいかないんだろう。
と思ったけど、よく考えたらパイプの先のコマンドは別プロセスで実行されるから set で環境変数を設定しても親プロセスには設定内容が反映されないんだった。
なので、こんな感じでパイプの中で変数を確認すると、ちゃんと設定されていることが分かる。
>echo foo | (set /p x=& set x) x=foo >set x 環境変数 x が定義されていません >set foo="foo" | (set bar="bar" & set foo & set bar) 環境変数 foo が定義されていません bar="bar" >
特に set とか echo は内部コマンドであるため、cmd /c set foo="foo" として、サブシェルを経由して呼び出しているイメージになる。
パイプを使った時の cmd.exe プロセスを見てみる
試しに以下のコマンドを実行して、別コンソールでプロセスを表示してみるとコマンド実行前:
>tasklist /fi "IMAGENAME eq cmd.exe" イメージ名 PID セッション名 セッション# メモリ使用量 ========================= ======== =============== ========= ========== cmd.exe 3200 Services 0 484 K cmd.exe 3348 Services 0 508 K cmd.exe 16648 Console 1 4,500 K cmd.exe 13084 Console 1 4,020 K
これを実行する。
>(timeout /t 10 /nobreak >NUL & echo foo) | set /p x=
コマンド実行中:
>tasklist /fi "IMAGENAME eq cmd.exe" イメージ名 PID セッション名 セッション# メモリ使用量 ========================= ======== =============== ========= ========== cmd.exe 3200 Services 0 484 K cmd.exe 3348 Services 0 508 K cmd.exe 16648 Console 1 4,500 K cmd.exe 13084 Console 1 4,020 K cmd.exe 9176 Console 1 3,684 K cmd.exe 14524 Console 1 3,212 K
実行前には存在しなかった cmd.exe が2つ起動していることが分かる。
コマンド実行後:
>tasklist /fi "IMAGENAME eq cmd.exe" イメージ名 PID セッション名 セッション# メモリ使用量 ========================= ======== =============== ========= ========== cmd.exe 3200 Services 0 484 K cmd.exe 3348 Services 0 508 K cmd.exe 16648 Console 1 4,500 K cmd.exe 13084 Console 1 4,020 K
実行後には実行前の cmd.exe のみが残っている。
また、パイプを使わないで以下のみを実行すると、実行中でも新しい cmd.exe は起動していないことが分かる。
>timeout /t 10 /nobreak >NUL & echo foo
コマンド実行中:
>tasklist /fi "IMAGENAME eq cmd.exe" イメージ名 PID セッション名 セッション# メモリ使用量 ========================= ======== =============== ========= ========== cmd.exe 3200 Services 0 484 K cmd.exe 3348 Services 0 508 K cmd.exe 16648 Console 1 4,500 K cmd.exe 13084 Console 1 4,020 K
まさにこれにハマっていて助かりました。
返信削除サブシェルがキーワードで、調べて理解が深まりました。
ありがとうございました。
コメントありがとうございます。
削除サブシェルははまりどころですよねー。