ファイル名を選択し、それを変数にパイプするプログラムを作成しようとしています。
私の試み:
Dir /B "C:\Program Files (x86)\ServerMaster\Internals\Versions\Van1" | (set /p myVar= & set myVar)
使用後は
myVar:1.14.4
計画ではエコーコマンドに入る予定だったので、このようにしました
@echo off
Dir /B "C:\Program Files (x86)\ServerMaster\Internals\Versions\Van1" | (set /p myVar= & set myVar)
echo e %myVar%
cmd /k
しかし、起こるのは
e
何が間違っているのでしょうか? また、FOR でこれを行う方法はありますか?
答え1
何が間違っているのでしょうか?
単純に、機能しないテクニックを使用しようとしています ;-) Windows パイプの動作方法により、パイプされたコマンド出力を使用して親環境で環境変数を設定することは不可能です。
スクリプトはコマンド プロセスで実行されています。これを親と呼びます。
Windows パイプは、それぞれ独自の環境スペースを持つ 2 つの子コマンド プロセスを起動します。パイプの左側は最初の子で実行され、右側は 2 番目の子で実行されます。パイプは、最初の子の出力を 2 番目の子の入力として送信します。SET /P
子プロセスで新しい myVar 変数が正常に定義され、SET MYVAR
コマンドによって値が表示されます。すばらしい。
しかし、パイプが終了すると、両方の子プロセスが終了し、関連付けられている環境は消えます。子パイプ プロセスから親環境に myVar 環境値を転送する方法はありません。
Windows パイプ設計には、メカニズムを完全に理解していない人を混乱させる驚くべき副作用が数多くあります。https://stackoverflow.com/q/8192318/1012053詳細については、質問とすべての回答を読むことをお勧めします。
FOR でこれを行う方法はありますか?
はい、環境変数でコマンドの出力をキャプチャする適切な方法は、具体的にはFOR /F
DavidPostill が示すように、FOR を使用することです。ただし、彼のコードには明確な問題が 1 つ、潜在的な問題が 1 つ、非効率な点が 1 つあります。
USEBACKQ
コマンドの出力を処理するときに使用する必要はありません。'
バックティックではなく、通常の一重引用符を使用する方が簡単です。for /f %%F in ('yourCommand') do ...
echo myVar:%myVar%
エラーは、FOR ループ本体内での使用です。myVar
行が解析されるときにパーセント拡張が行われ、FOR ループ全体が 1 つのステップで解析されるため、ループの実行前に存在していた値が表示されます。ループ内で設定された値を表示するには、遅延拡張 ( setlocal enableDelayedExpansion
) を有効にしてから、 を使用する必要がありますecho !myVar!
。
別の問題が発生する可能性があります - FOR /F は値をスペースで区切られたトークンに解析し、最初のトークンのみをキャプチャします。ファイル名にスペースが含まれている場合は、DELIMS オプションを使用して区切り文字を指定しない限り、名前全体を取得できません。
for /f "delims=" %%F in (....) do ....
DIR /B
しかし、と を使用する必要はありません。 オプションなしで、FOR /F
単純にバニラ ループを使用できます。FOR
/F
たとえば、次の例ではすべてのファイルがリストされます。
for %%F in ("C:\Program Files (x86)\ServerMaster\Internals\Versions\Van1\*") do echo %%~nxF
~nx
ドライブとフォルダー パスを破棄し、ファイル名と拡張子のみを使用するように指定します。
通常、環境変数を使用する必要はありません。%%F
ループ内で FOR 変数を使用して作業を行うだけです。
しかし、何らかの理由でループの外で値が必要な場合は、次のようにすることができます。
for %%F in ("C:\Program Files (x86)\ServerMaster\Internals\Versions\Van1\*") do set "myVar=%%~nxF"
しかし、これでは反復される最後のファイルしかキャプチャされません。myVar 変数は反復ごとに上書きされます。元の設計では、リストされた最初のファイルがキャプチャされます (動作するようにできたと仮定した場合)。Van1 フォルダーに 1 つのファイルしか含まれていないという事実がわかっているのでなければ、どちらも良いアイデアとは思えません。
すべてのファイルを変数に取り込む必要がある場合は、疑似配列を使用する必要があります。バッチには正式な配列の概念はありませんが、簡単にエミュレートできます。Web で「batchfile array」を検索するだけで、多数の例を見つけることができます。