web-dev-qa-db-fra.com

Affecter la sortie d'un programme à une variable à l'aide d'un fichier de commandes MS

J'ai besoin d'assigner la sortie d'un programme à une variable à l'aide d'un fichier de traitement par lots MS.

Donc, dans GNU Bash Shell, j'utiliserais VAR=$(application arg0 arg1). J'ai besoin d'un comportement similaire dans Windows en utilisant un fichier de commandes.

Quelque chose comme set VAR=application arg0 arg1.

230
initialZero

Une façon est:

application arg0 arg1 > temp.txt
set /p VAR=<temp.txt

Un autre est:

for /f %%i in ('application arg0 arg1') do set VAR=%%i

Notez que le premier % dans %%i est utilisé pour échapper au % après et est nécessaire pour utiliser le code ci-dessus dans un fichier de commandes plutôt que sur la ligne de commande. Imaginez, votre test.bat a quelque chose comme:

for /f %%i in ('c:\cygwin64\bin\date.exe +"%%Y%%m%%d%%H%%M%%S"') do set datetime=%%i
echo %datetime%
353
Carlos Gutiérrez

En complément de cette réponse précédente , les pipes peuvent être utilisées dans une instruction for, échappée par un symbole caret:

    for /f "tokens=*" %%i in ('tasklist ^| grep "Explorer"') do set VAR=%%i
57
Renat

@OP, vous pouvez utiliser pour les boucles pour capturer l’état de retour de votre programme, s’il affiche autre chose que des nombres

8
ghostdog74

en supposant que la sortie de votre application est un code de retour numérique, vous pouvez effectuer les opérations suivantes:

application arg0 arg1
set VAR=%errorlevel%
6
akf

Lors de l’exécution: for /f %%i in ('application arg0 arg1') do set VAR=%%i j’obtenais une erreur: %% j’étais inattendu à ce moment. .__ En guise de solution, je devais exécuter la fonction for /f %i in ('application arg0 arg1') do set VAR=%i ci-dessus

5
Munish Mehta

En plus de la réponse, vous ne pouvez pas utiliser directement les opérateurs de redirection de sortie dans la partie set de la boucle for (par exemple, si vous souhaitez masquer la sortie stderror d'un utilisateur et fournir un message d'erreur plus clair). Au lieu de cela, vous devez leur échapper avec un caractère caret (^):

for /f %%O in ('some-erroring-command 2^> nul') do (echo %%O)

Référence: Redirige la sortie de la commande dans la boucle for du script batch

1
Kubo2
@echo off
SETLOCAL ENABLEDELAYEDEXPANSION

REM Prefer backtick usage for command output reading:
REM ENABLEDELAYEDEXPANSION is required for actualized
REM  outer variables within for's scope;
REM within for's scope, access to modified 
REM outer variable is done via !...! syntax.

SET CHP=C:\Windows\System32\chcp.com

FOR /F "usebackq tokens=1,2,3" %%i IN (`%CHP%`) DO (
    IF "%%i" == "Aktive" IF "%%j" == "Codepage:" (
        SET SELCP=%%k
        SET SELCP=!SELCP:~0,-1!
    )
)
echo actual codepage [%SELCP%]

ENDLOCAL
0
rcm

Vous pouvez utiliser une macro batch pour une capture simple des sorties de commande, un peu comme le comportement du shell bash. 

L'utilisation de la macro est simple et ressemble à

%$set% VAR=application arg1 arg2

Et ça marche même avec des pipes

%$set% allDrives="wmic logicaldisk get name /value | findstr "Name""

La macro utilise la variable comme un tableau et stocke chaque ligne dans un index séparé.
Dans l'exemple de %$set% allDrives="wmic logicaldisk, les variables suivantes seront créées: 

allDrives.Len=5
allDrives.Max=4
allDrives[0]=Name=C:
allDrives[1]=Name=D:
allDrives[2]=Name=F:
allDrives[3]=Name=G:
allDrives[4]=Name=Z:

Pour l'utiliser, il n'est pas important de comprendre le fonctionnement de la macro elle-même.

L'exemple complet

@echo off
setlocal

call :initMacro

%$set% ipOutput="ipconfig"
call :ShowVariable ipOutput
echo First line is %ipOutput[0]%

echo( 
%$set% driveNames="wmic logicaldisk get name /value | findstr "Name""
call :ShowVariable driveNames

exit /b

:ShowVariable
setlocal EnableDelayedExpansion
for /L %%n in (1 1 !%~1.len!) do (
    echo %%n: !%~1[%%n]!
)
echo(
exit /b

:initMacro
if "!!"=="" (
    echo ERROR: Delayed Expansion must be disabled while defining macros
    (goto) 2>nul
    (goto) 2>nul
)
(set \n=^^^
%=empty=%
)

set $set=FOR /L %%N in (1 1 2) DO IF %%N==2 ( %\n%
    for /f "tokens=1,* delims== " %%1 in ("!argv!") do (            %\n%
        endlocal                                                    %\n%
        endlocal                                                    %\n%
        set "%%~1.Len=0"                                            %\n%
        if "!!"=="" (                                               %\n%
            %= Used if delayed expansion is enabled =%              %\n%
            for /F "delims=" %%O in ('"%%~2 | findstr /N ^^"') do ( %\n%
                setlocal DisableDelayedExpansion                    %\n%
                set pathExt=:                                       %\n%
                set "line=%%O"                                      %\n%
                call set ^"line=%%line:"="Q"%%"                     %\n%
                call set "line=%%line:!="B"!%%"                     %\n%
                setlocal EnableDelayedExpansion                     %\n%
                set "line=!line:^=^^!"                              %\n%
                set "line=!line:"B"=^!"                             %\n%
                set "line=!line:"Q"=^"!^"                           %\n%
                set "line="!line:*:=!""                             %\n%
                for /F %%C in ("!%%~1.Len!") DO (                   %\n%
                    FOR /F "delims=" %%L in ("!line!") DO (         %\n%
                        endlocal                                    %\n%
                        endlocal                                    %\n%
                        set "%%~1[%%C]=%%~L" !                      %\n%
                    )                                               %\n%
                    set /a %%~1.Len+=1                              %\n%
                )                                                   %\n%
            )                                                       %\n%
        ) ELSE (                                                    %\n%
            %= Used if delayed expansion is disabled =%             %\n%
            for /F "delims=" %%O in ('"%%~2 | findstr /N ^^"') do ( %\n%
                setlocal DisableDelayedExpansion                    %\n%
                set "line=%%O"                                      %\n%
                setlocal EnableDelayedExpansion                     %\n%
                set "line="!line:*:=!""                             %\n%
                for /F %%C in ("!%%~1.Len!") DO (                   %\n%
                    FOR /F "delims=" %%L in ("!line!") DO (         %\n%
                        endlocal                                    %\n%
                        endlocal                                    %\n%
                        set "%%~1[%%C]=%%~L"                        %\n%
                    )                                               %\n%
                    set /a %%~1.Len+=1                              %\n%
                )                                                   %\n%
            )                                                       %\n%
        )                                                           %\n%
        set /a %%~1.Max=%%~1.Len-1                                  %\n%
        )                                                           %\n%
    ) else setlocal EnableDelayedExpansion^&setlocal^&set argv=

goto :eof
0
jeb

J'ai écrit le script qui pings google.com toutes les 5 secondes et en enregistrant les résultats avec l'heure actuelle. Vous pouvez trouver ici la sortie des variables "commandLineStr" (avec index)

@echo off

:LOOPSTART

echo %DATE:~0% %TIME:~0,8% >> Pingtest.log

SETLOCAL ENABLEDELAYEDEXPANSION
SET scriptCount=1
FOR /F "tokens=* USEBACKQ" %%F IN (`ping google.com -n 1`) DO (
  SET commandLineStr!scriptCount!=%%F
  SET /a scriptCount=!scriptCount!+1
)
@ECHO %commandLineStr1% >> PingTest.log
@ECHO %commandLineStr2% >> PingTest.log
ENDLOCAL

timeout 5 > nul

GOTO LOOPSTART
0
Ja Vy