web-dev-qa-db-ja.com

Windowsの変数でコマンドの結果を取得するにはどうすればよいですか?

コマンドの結果をWindowsバッチスクリプトの変数として取得しようとしています(bashスクリプトの同等物については bashでコマンドの結果を取得する方法 を参照してください)。 .batファイルで機能するソリューションが推奨されますが、他の一般的なWindowsスクリプトソリューションも歓迎します。

120
John Meagher

すべてのコマンド出力をキャプチャする必要がある場合は、次のようなバッチを使用できます。

@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に保存されます。

@ジョン:これには実用的な用途はありますか? PowerShellや、スクリプトタスクを簡単に実行できる他のプログラミング言語(Python、Perl、PHP、Ruby)を見る必要があると思います

31
PabloG

謙虚な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"
77
tardate

現在のディレクトリを取得するには、これを使用できます:

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

しかし、より強力な別のシェルへの移行を検討するか、このようなアプリケーションを作成することをお勧めします。バッチファイルの可能性をかなり広げています。

23
Evil Activity

パラメーター/Pを指定したSETコマンドを使用し、それに出力を送る必要があります。たとえば、 http://www.ss64.com/nt/set.html を参照してください。 .BATファイルについてはわかりませんが、CMDで動作します

この投稿へのコメントから:

このリンクには、Set /P _MyVar=<MyFilename.txtの最初の行に_MyVarを設定するという「MyFilename.txt」というコマンドがあります。これは、「myCmd > tmp.txt」とともに「set /P myVar=<tmp.txt」として使用できます。ただし、すべての出力ではなく、出力の最初の行のみを取得します

8
Ilya Kochetov

「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
5
PabloG

FORコマンドの結果を使用するだけです。例(バッチファイル内):

for /F "delims=" %%I in ('dir /b /a-d /od FILESA*') do (echo %%I)

%%Iを必要な値として使用できます。このように:%%I

事前に%%IにはスペースやCR文字がなく、比較に使用できます!!

3
Raceableability

上記のソリューションにコメントを追加したいと思います。

これらの構文はすべて、コマンドISがパス内で見つかった場合、またはコマンドISスペースなしのcmdpath OR特殊文字の場合に完全に機能します。

ただし、パスに特殊文字が含まれるフォルダーにある実行可能コマンドを使用しようとすると、コマンドパスを二重引用符( ")で囲む必要があり、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.

その場合、コマンドを使用してその結果を変数に格納することがわかった唯一の解決策は、デフォルトのディレクトリをコマンド自体の1つに(一時的に)設定することです:

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」構文を使用できるように、バッチスクリプトが実行可能コマンドの1つと同じフォルダーにあると想定しています。これが当てはまらない場合は、コマンドパスを見つけてデフォルトディレクトリをそのパスに変更する方法を見つける必要があります。

注意:不思議な人のために、ここで(フォルダーを選択するために)使用するサンプルコマンドはFOLDERBROWSE.EXEです。 Webサイトf2ko.de( http://f2ko.de/en/cmd.php )で見つけました。

複雑なパスを介してアクセスできるこの種のコマンドに対して、より良いソリューションがあれば、それを聞いてとてもうれしいです。

ジル

2
@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%"
2
Hike

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に追加します

[クレジット]Windows XPコマンド ページの他のすべての回答といくつかの掘り下げに感謝。

2
Gustavo Carreno

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=!
    )
)
1
Adam Mitz

forコマンドを使用する必要があります。以下に例を示します。

@echo off
rem Commands go here
exit /b
:output
for /f "tokens=* useback" %%a in (`%~1`) do set "output=%%a"

call :output "Command goes here"を使用すると、出力は%output%変数に格納されます。

注:複数行のコマンド出力がある場合、このツールは、複数行コマンドの最終行への出力をsetします。

0
Hayz
@echo off
setlocal EnableDelayedExpansion
FOR /F "tokens=1 delims= " %%i IN ('echo hola') DO (
    set TXT=%%i
)
echo 'TXT: %TXT%'

結果は「TXT:hola」です

0
ivan rc