Вопрос по windows – Как получить результат команды в переменной в Windows?

114

Я надеюсь получить результат команды как переменную в пакетном скрипте Windows (см.как получить результат команды в bash для эквивалентного сценария bash). Решение, которое будет работать в .bat-файле, предпочтительнее, но приветствуются и другие распространенные сценарии Windows.

Джон, до смешного трудно найти этоvery полезный вопрос. Не могли бы вы рассмотреть возможность добавления альтернативных фраз, какHow to capture the output of a a program into a variable in a Windows batch file? Piotr Dobrogost
@MichaelFreidgeim этот вопрос фактически задавался за 2 года до этого дубликата, но есть многократные дубликаты этого вопроса. Смотрите комментарии наstackoverflow.com/questions/6359820/… icc97
Возможный дубликатWindows batch assign output of a program to a variable Michael Freidgeim
Google показала эту страницу на 3-м месте. René Nyffenegger
@ icc97, & quot; Возможный дубликат & quot; это способ убрать - закрыть похожие вопросы и оставить один с лучшими ответами. Дата не обязательна. Увидетьmeta.stackexchange.com/questions/147643/… Если вы согласны, что это требует разъяснений, пожалуйста, проголосуйтеmeta.stackexchange.com/questions/281980/…  Если вы видите несколько дубликатов, вы должны выбрать один из них как канонический и проголосовать, чтобы закрыть другие. Michael Freidgeim

Ваш Ответ

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

2

Используя результат команды в качестве аргумента в 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
This will call itself with the result of the CD command, same as pwd. String extraction on parameters will return the filename/folder. Get the contents of this folder and append to the filename.txt

[Credits]: Спасибо за все остальные ответы и некоторые раскопки наКоманды Windows XP стр.

76

for Команда накопила некоторые интересные возможности за эти годы:

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

Обратите внимание, что"delims=" перезаписывает пробел по умолчанию и разделители табуляции, так что выходные данные команды date будут сожраны все сразу.

Для захвата многострочного вывода он по-прежнему может быть однострочным (используя переменную 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"
Error: User Rate Limit Exceeded%Error: User Rate Limit Exceededfor /f "delims=" %%i in ('date +%F_%H-%M-%S') do set now=%%i
Error: User Rate Limit ExceededforError: User Rate Limit Exceeded%Error: User Rate Limit Exceeded%%.
Error: User Rate Limit Exceeded John Meagher
Error: User Rate Limit ExceededFOR /F "delims=" %%i IN ('date /t') DO set today=%%i
23

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

Хотя он использует временный файл, поэтому он не самый красивый, но он, безусловно, работает! & APOS; CD-& APOS; помещает текущий каталог в «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

Но вы можете захотеть перейти на другую более мощную оболочку или создать приложение для этого. Это значительно расширяет возможности пакетных файлов.

Error: User Rate Limit Exceeded John Meagher
Error: User Rate Limit Exceeded
1

Все эти синтаксисы работают отлично, ЕСЛИ ВАША КОМАНДА НАХОДИТСЯ В ПУТИ, или ЕСЛИ КОМАНДА - КОМАНДА, БЕЗ ПРОСТРАНСТВ ИЛИ ОСОБЫХ СИМВОЛОВ

Но если вы попытаетесь использовать исполняемую команду, расположенную в папке, путь к которой содержит специальные символы, вам потребуется заключить путь к команде в двойные кавычки (& quot;), и тогда синтаксис 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 . . .

Конечно, в приведенном выше примере я предполагаю, что мой пакетный скрипт находится в той же папке, что и моя исполняемая команда, так что я могу использовать & quot;% ~ d0% ~ p0 & quot; синтаксис. Если это не ваш случай, вам нужно найти способ найти путь к вашей команде и изменить каталог по умолчанию на его путь.

NB. Для тех, кто интересуется, здесь приведен пример команды (для выбора папки) FOLDERBROWSE.EXE. Я нашел это на веб-сайте f2ko.de (http://f2ko.de/en/cmd.php).

Если у кого-то есть лучшее решение для такого рода команд, доступное по сложному пути, я буду очень рад услышать об этом.

жилль

Error: User Rate Limit ExceededCALL "%SOURCEDIR%\FOLDERBROWSE" ... "quoted parameters"Error: User Rate Limit Exceeded
Error: User Rate Limit ExceededCALL. FOR /F doesn't work if path has spaces
7

вам нужно использоватьSET команда с параметром/P и направьте свой вывод на него. Например, см.http://www.ss64.com/nt/set.html, Будет работать для CMD, не уверен насчет файлов .BAT

Из комментария к этому посту:

That link has the command "Set /P _MyVar=<MyFilename.txt" which says it will set _MyVar to the first line from MyFilename.txt. This could be used as "myCmd > tmp.txt" with "set /P myVar=<tmp.txt". But it will only get the first line of the output, not all the output

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded John Meagher
5

V & quot; переменная окружения самый последний файл

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

в пакетном файле вы должны использовать двойной префикс в переменной цикла:

FOR /F %%I IN ('DIR *.* /O:D /B') DO SET V=%%I
Error: User Rate Limit Exceeded John Meagher
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%

Вторая версия, если вам нужно распечатать содержимое построчно. Это использует тот факт, что не будет дублированных строк вывода из «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=!
    )
)
29

вы можете использовать такой пакет:

@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)

Error: User Rate Limit Exceededfor loopError: User Rate Limit Exceeded
Ответ в одной строке решит конкретный случай, который у меня есть. Я просто подумал, что есть вариант с несколькими строками (или более простой вариант с одной строкой). Я предполагаю, что возможности файлов bat просто не так уж хороши. Это необходимо для сценариев летучих мышей, обертывающих Java-приложения. Строительство в основном классных путей. John Meagher
is there any practical use for this? Вы шутите? Это все время используется в других оболочках (я полагаю, во всех GNU / Linux), и этоvery полезно.
Error: User Rate Limit Exceeded
Есть практическое применение, на самом деле ... вроде. Я хочу использовать сценарий PowerShell, чтобы найти конкретный путь Visual Studio, но из этого пути мне нужен пакетный файл, который устанавливает несколько переменных env, чтобы я мог вызвать editbin ... Поэтому мне нужно найти путь и вернуть его в вызывающий экземплярcmd так что я могу запустить его там. ... Да, это так же ужасно, как звуки. Visual Studio заставляет меня иногда плакать. @ Ajedi32 я думаюyou хотел сказать, чтоbatch сценарии - ужасная реликвия прошлого. ;)
3

FOR команда. Например (внутри командного файла):

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

Вы можете использовать%%I как значение, которое вы хотите. Именно так:%%I.

И заранее%%I не имеет пробелов или символов CR и может использоваться для сравнения !!

-1

http://technet.microsoft.com/en-us/library/bb490982.aspx который объясняет, что вы можете сделать с выводом команды.

Error: User Rate Limit Exceededgit pull>0 set /P RESULTVAR=<0Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded John Meagher
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%"
Спасибо за публикацию ответа! Хотя фрагмент кода может дать ответ на вопрос, все же здорово добавить некоторую дополнительную информацию, например, объяснить и т. Д.

Похожие вопросы