コマンドの結果を Windows バッチ スクリプトの変数として取得しようとしています ( bash スクリプトに相当するものについては、bash でコマンドの結果を取得する方法を参照してください)。.bat ファイルで機能するソリューションが推奨されますが、他の一般的な Windows スクリプト ソリューションも歓迎されます。
13 に答える
humble forコマンドは、何年にもわたっていくつかの興味深い機能を蓄積してきました。
D:\> FOR /F "delims=" %i IN ('date /t') DO set today=%i
D:\> echo %today%
Sat 20/09/2008
"delims="
デフォルトのスペースとタブ区切り文字を上書きして、date コマンドの出力が一度に飲み込まれることに注意してください。
複数行の出力をキャプチャするために、基本的には 1 行にすることができます (変数 lf を結果の変数の区切り記号として使用します)。
REM NB:in a batch file, need to use %%i not %i
setlocal EnableDelayedExpansion
SET lf=-
FOR /F "delims=" %%i IN ('dir \ /b') DO if ("!out!"=="") (set out=%%i) else (set out=!out!%lf%%%i)
ECHO %out%
パイプ式をキャプチャするには、次を使用します^|
。
FOR /F "delims=" %%i IN ('svn info . ^| findstr "Root:"') DO set "URL=%%i"
すべてのコマンド出力をキャプチャする必要がある場合は、次のようなバッチを使用できます。
@ECHO OFF
IF NOT "%1"=="" GOTO ADDV
SET VAR=
FOR /F %%I IN ('DIR *.TXT /B /O:D') DO CALL %0 %%I
SET VAR
GOTO END
:ADDV
SET VAR=%VAR%!%1
:END
すべての出力行は、「!」で区切られたVARに格納されます。
But if only a single-line console-output is expected, try:
@ECHO off
@SET MY_VAR=
FOR /F %%I IN ('npm prefix') DO @SET "MY_VAR=%%I"
@REM Do something with MY_VAR variable...
@John: is there any practical use for this? I think you should watch PowerShell or any other programming language capable to perform scripting tasks easily (Python, Perl, PHP, Ruby)
現在のディレクトリを取得するには、これを使用できます。
CD > tmpFile
SET /p myvar= < tmpFile
DEL tmpFile
echo test: %myvar%
ただし、一時ファイルを使用しているため、最もきれいではありませんが、確かに機能します! 「CD」は現在のディレクトリを「tmpFile」に置き、「SET」は tmpFile の内容を読み込みます。
「配列」を使用した複数行の解決策は次のとおりです。
@echo off
rem ---------
rem Obtain line numbers from the file
rem ---------
rem This is the file that is being read: You can replace this with %1 for dynamic behaviour or replace it with some command like the first example i gave with the 'CD' command.
set _readfile=test.txt
for /f "usebackq tokens=2 delims=:" %%a in (`find /c /v "" %_readfile%`) do set _max=%%a
set /a _max+=1
set _i=0
set _filename=temp.dat
rem ---------
rem Make the list
rem ---------
:makeList
find /n /v "" %_readfile% >%_filename%
rem ---------
rem Read the list
rem ---------
:readList
if %_i%==%_max% goto printList
rem ---------
rem Read the lines into the array
rem ---------
for /f "usebackq delims=] tokens=2" %%a in (`findstr /r "\[%_i%]" %_filename%`) do set _data%_i%=%%a
set /a _i+=1
goto readList
:printList
del %_filename%
set _i=1
:printMore
if %_i%==%_max% goto finished
set _data%_i%
set /a _i+=1
goto printMore
:finished
ただし、別のより強力なシェルへの移行を検討するか、このようなアプリケーションを作成することをお勧めします。バッチファイルの可能性をかなり広げています。
SET
パラメータを指定してコマンドを使用し/P
、出力をそこに送る必要があります。たとえば、http://www.ss64.com/nt/set.htmlを参照してください。CMDで動作しますが、.BATファイルについては不明です
コメントからこの投稿へ:
そのリンクには、の最初の行
Set /P _MyVar=<MyFilename.txt
に設定するというコマンド " " があります。これは、" " とともに " "として使用できます。ただし、すべての出力ではなく、出力の最初の行のみを取得します_MyVar
MyFilename.txt
myCmd > tmp.txt
set /P myVar=<tmp.txt
環境変数「V」に最新ファイルを設定する例
FOR /F %I IN ('DIR *.* /O:D /B') DO SET V=%I
バッチ ファイルでは、ループ変数で二重プレフィックスを使用する必要があります。
FOR /F %%I IN ('DIR *.* /O:D /B') DO SET V=%%I
上記のソリューションにコメントを追加したいと思います。
コマンドがパス内にある場合、またはコマンドがスペースや特殊文字を含まない cmdpath である場合、これらの構文はすべて完全に機能します。
ただし、特殊文字を含むパスにある実行可能コマンドを使用しようとすると、コマンド パスを二重引用符 (") で囲む必要があり、FOR /F 構文は機能しません。
例:
$ for /f "tokens=* USEBACKQ" %f in (
`""F:\GLW7\Distrib\System\Shells and scripting\f2ko.de\folderbrowse.exe"" Hello '"F:\GLW7\Distrib\System\Shells and scripting"'`
) do echo %f
The filename, directory name, or volume label syntax is incorrect.
また
$ for /f "tokens=* USEBACKQ" %f in (
`"F:\GLW7\Distrib\System\Shells and scripting\f2ko.de\folderbrowse.exe" "Hello World" "F:\GLW7\Distrib\System\Shells and scripting"`
) do echo %f
'F:\GLW7\Distrib\System\Shells' is not recognized as an internal or external command, operable program or batch file.
また
`$ for /f "tokens=* USEBACKQ" %f in (
`""F:\GLW7\Distrib\System\Shells and scripting\f2ko.de\folderbrowse.exe"" "Hello World" "F:\GLW7\Distrib\System\Shells and scripting"`
) do echo %f
'"F:\GLW7\Distrib\System\Shells and scripting\f2ko.de\folderbrowse.exe"" "Hello' is not recognized as an internal or external command, operable program or batch file.
その場合、コマンドを使用してその結果を変数に格納するために私が見つけた唯一の解決策は、(一時的に) デフォルト ディレクトリをコマンド自体のディレクトリに設定することです。
pushd "%~d0%~p0"
FOR /F "tokens=* USEBACKQ" %%F IN (
`FOLDERBROWSE "Hello world!" "F:\GLW7\Distrib\System\Layouts (print,display...)"`
) DO (SET MyFolder=%%F)
popd
echo My selected folder: %MyFolder%
結果は正しいです。
My selected folder: F:\GLW7\Distrib\System\OS install, recovery, VM\
Press any key to continue . . .
もちろん、上記の例では、"%~d0%~p0" 構文を使用できるように、バッチ スクリプトが実行可能コマンドと同じフォルダーにあると想定しています。これが当てはまらない場合は、コマンド パスを見つけて、デフォルト ディレクトリをそのパスに変更する方法を見つける必要があります。
注: 疑問に思われる方のために説明すると、ここで (フォルダーを選択するために) 使用されるサンプル コマンドは FOLDERBROWSE.EXE です。Web サイト f2ko.de ( http://f2ko.de/en/cmd.php ) で見つけました。
複雑なパスを介してアクセスできるこの種のコマンドに対するより良い解決策を誰かが持っている場合は、それを聞いて非常に嬉しく思います.
ジル
コマンドの結果を bash の引数として使用するで提供されている解決策を探している場合は?
次に、コードは次のとおりです。
@echo off
if not "%1"=="" goto get_basename_pwd
for /f "delims=X" %%i in ('cd') do call %0 %%i
for /f "delims=X" %%i in ('dir /o:d /b') do echo %%i>>%filename%.txt
goto end
:get_basename_pwd
set filename=%~n1
:end
- これは、pwd と同じように、CD コマンドの結果で自分自身を呼び出します。
- パラメータで文字列を抽出すると、ファイル名/フォルダが返されます。
- このフォルダーの内容を取得し、filename.txt に追加します。
[Credits] : 他のすべての回答と、 Windows XP コマンドページの掘り下げに感謝します。
@echo off
ver | find "6.1." > nul
if %ERRORLEVEL% == 0 (
echo Win7
for /f "delims=" %%a in ('DIR "C:\Program Files\Microsoft Office\*Outlook.EXE" /B /P /S') do call set findoutlook=%%a
%findoutlook%
)
ver | find "5.1." > nul
if %ERRORLEVEL% == 0 (
echo WinXP
for /f "delims=" %%a in ('DIR "C:\Program Files\Microsoft Office\*Outlook.EXE" /B /P /S') do call set findoutlook=%%a
%findoutlook%
)
echo Outlook dir: %findoutlook%
"%findoutlook%"
すべての出力を 1 つの変数に取り込むことができますが、行は実際の CR-LF ではなく、選択した文字 (以下の例では #) で区切られます。
@echo off
setlocal EnableDelayedExpansion
for /f "delims=" %%i in ('dir /b') do (
if "!DIR!"=="" (set DIR=%%i) else (set DIR=!DIR!#%%i)
)
echo directory contains:
echo %DIR%
2 番目のバージョン。内容を 1 行ずつ出力する必要がある場合。これは、「dir /b」からの出力行が重複しないという事実を利用しているため、一般的なケースでは機能しない可能性があります。
@echo off
setlocal EnableDelayedExpansion
set count=0
for /f "delims=" %%i in ('dir /b') do (
if "!DIR!"=="" (set DIR=%%i) else (set DIR=!DIR!#%%i)
set /a count = !count! + 1
)
echo directory contains:
echo %DIR%
for /l %%c in (1,1,%count%) do (
for /f "delims=#" %%i in ("!DIR!") do (
echo %%i
set DIR=!DIR:%%i=!
)
)
コマンド出力で何ができるかを説明しているこのhttp://technet.microsoft.com/en-us/library/bb490982.aspxを参照してください。