it-swarm-eu.dev

Jak získám výsledek příkazu v proměnné v systému Windows?

Hledám výsledek příkazu jako proměnné v dávkovém skriptu Windows (viz jak získat výsledek příkazu v bash pro bash skriptovací ekvivalent). Upřednostňuje se řešení, které bude fungovat v souboru .bat, ale jsou vítána i další běžná řešení pro skriptování v systému Windows. 

111
John Meagher

Pokud musíte zachytit všechny výstupy příkazů, můžete použít dávku jako je tato:

@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

Všechny výstupní linky jsou uloženy v VAR oddělené znakem "!".

@ John: existuje pro to nějaké praktické využití? Myslím, že byste měli sledovat PowerShell nebo jakýkoli jiný programovací jazyk, který je schopen provádět skriptovací úlohy snadno (Python, Perl, PHP, Ruby)

29
PabloG

Pokorný pro příkaz během let nahromadil několik zajímavých schopností:

D:\> FOR /F "delims=" %i IN ('date /t') DO set today=%i
D:\> echo %today%
Sat 20/09/2008

Všimněte si, že "delims=" přepíše výchozí mezery a oddělovače karet tak, aby výstup příkazu data získal všechny najednou.

Chcete-li zachytit víceřádkový výstup, může být stále v podstatě jedním řádkem (pomocí proměnné lf jako oddělovače ve výsledné proměnné):

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%

Chcete-li zachytit výraz piped, použijte ^|:

FOR /F "delims=" %%i IN ('svn info . ^| findstr "Root:"') DO set "URL=%%i"
75
tardate

Chcete-li získat aktuální adresář, můžete jej použít:

CD > tmpFile
SET /p myvar= < tmpFile
DEL tmpFile
echo test: %myvar%

Používá však temp-soubor, takže to není nejkrásnější, ale určitě to funguje! 'CD' vloží aktuální adresář do 'tmpFile', 'SET' načte obsah tmpFile.

Zde je řešení pro více řádků s "pole":

@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

Ale možná budete chtít zvážit přesunutí do jiné mocnější Shell nebo vytvořit aplikaci pro tyto věci. Je to natažení možností dávkových souborů docela dost.

23
Evil Activity

musíte použít příkaz SET s parametrem /P a nasměrovat na něj výstup. Například viz http://www.ss64.com/nt/set.html . Bude pracovat pro CMD, není jisté o souborech .BAT

Z komentáře k tomuto příspěvku:

Tento odkaz má příkaz "Set /P _MyVar=<MyFilename.txt", který říká, že nastaví _MyVar na první řádek Z MyFilename.txt. To může být Použité jako "myCmd > tmp.txt" s "set /P myVar=<tmp.txt". Ale pouze Dostane první řádek výstupu, ne Veškerý výstup

7
Ilya Kochetov

Příklad nastavit v proměnné prostředí "V" nejnovější soubor 

FOR /F %I IN ('DIR *.* /O:D /B') DO SET V=%I

v dávkovém souboru musíte použít dvojitou předponu v proměnné smyčky:

FOR /F %%I IN ('DIR *.* /O:D /B') DO SET V=%%I
5
PabloG

Stačí použít výsledek příkazu FOR. Například (uvnitř dávkového souboru):

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

%%I můžete použít jako požadovanou hodnotu. Takhle: %%I.

%%I předem nemá žádné mezery ani znaky CR a může být použit pro srovnání !!

3
Raceableability
@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

Pokud hledáte řešení uvedené v Použití výsledku příkazu jako argumentu v bash?

pak je zde kód:

@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
  • Tímto způsobem se vyvolá výsledek příkazu CD, stejně jako příkaz pwd.
  • Extrakce řetězce na parametrech vrátí název souboru/složky.
  • Získejte obsah této složky a připojte soubor.txt

[Credits]: Díky všem ostatním odpovědím a některým kopáním příkazů Windows XP page.

2
Gustavo Carreno

Můžete zachytit veškerý výstup v jedné proměnné, ale řádky budou odděleny znakem dle vašeho výběru (# v příkladu níže) namísto skutečného 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%

Druhá verze, pokud potřebujete vytisknout obsah řádek po řádku. To má za následek skutečnost, že nebudou existovat duplicitní řádky výstupu z "dir/b", takže to nemusí fungovat v obecném případě.

@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

K výše uvedeným řešením bych rád přidal poznámku:

Všechny tyto syntaxe fungují dobře, pokud VAŠE PŘÍKAZ IS NALEZNETE V RÁMCI PATHU, POKUD JE PŘÍKAZ IS cmdpath BEZ PROSTORŮ OR ZVLÁŠTNÍ ZNAKY.

Pokud se však pokusíte použít spustitelný příkaz, který se nachází ve složce, která obsahuje speciální znaky, je třeba uzavřít cestu příkazů do dvojitých uvozovek (") a syntaxe FOR/F nefunguje.

Příklady:

$ 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.

nebo 

$ 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.

nebo 

`$ 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.

V takovém případě je jediným řešením, které jsem zjistil, použít příkaz a uložit jeho výsledek do proměnné, nastavit (dočasně) výchozí adresář na příkaz samotný:

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%

Výsledek je pak správný:

My selected folder: F:\GLW7\Distrib\System\OS install, recovery, VM\
Press any key to continue . . .

Samozřejmě ve výše uvedeném příkladu předpokládám, že můj dávkový skript je umístěn ve stejné složce jako můj spustitelný příkaz, takže můžu použít syntaxi "% ~ d0% ~ p0". Pokud se nejedná o váš případ, musíte najít způsob, jak najít cestu k příkazu a změnit výchozí adresář na jeho cestu.

Poznámka: Pro ty, kteří se zajímají, je vzorový příkaz použitý zde (pro výběr složky) FOLDERBROWSE.EXE. Našel jsem ho na webových stránkách f2ko.de ( http://f2ko.de/en/cmd.php ).

Pokud má někdo lepší řešení pro tento druh příkazů přístupných prostřednictvím složité cesty, budu velmi rád, že o tom budu slyšet.

Gilles

1

Měli byste použít příkaz for, zde je příklad:

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

a můžete použít call :output "Command goes here" pak bude výstup v proměnné %output%.

Poznámka: Pokud máte příkazový výstup, který je víceřádkový, tento nástroj bude set výstup na poslední řádek vašeho příkazu multiline.

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

výsledek je 'TXT: hola'

0
ivan rc