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

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

Джон, найти этот полезный вопрос о очень до смешного сложно. Не могли бы вы подумать о добавлении альтернативной формулировки, например Как захватыватьвыход из программа в переменную в командном файле Windows?

Piotr Dobrogost 22.10.2011 17:35

Google показал эту страницу на 3-м месте.

René Nyffenegger 07.12.2012 01:19

Возможный дубликат Пакет Windows назначает вывод программы переменной

Michael Freidgeim 12.03.2017 02:15

@MichaelFreidgeim, этот вопрос на самом деле задавали за 2 года до этого дубликата, но есть несколько дубликатов этого вопроса. См. Комментарии к stackoverflow.com/questions/6359820/…

icc97 31.05.2017 18:50

@ icc97, «Возможный дубликат» - это способ очистки - закрыть похожие вопросы и оставить один с лучшими ответами. Дата не важна. См. meta.stackexchange.com/questions/147643/…. Если вы согласны с тем, что это требует разъяснения, проголосуйте за meta.stackexchange.com/questions/281980/…. Если вы видите несколько дубликатов, вы должны выбрать один как канонический и проголосовать за закрытие других.

Michael Freidgeim 01.06.2017 01:41

@MichaelFreidgeim Справедливое замечание, я бы сказал, что эти вопросы были исключением, их всего около четырех, все они были заданы много лет назад, у них разные качества ответов на каждый, и ни один из них не является окончательным.

icc97 01.06.2017 08:53
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
145
6
268 756
13
Перейти к ответу Данный вопрос помечен как решенный

Ответы 13

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

В этой статье рассматривается только перенаправление и связанные темы. Он не отвечает на вопрос, как получить результат одной команды и преобразовать его в переменную.

John Meagher 20.09.2008 19:34

Используя его ответ, я придумал следующее: git pull>0 set /P RESULTVAR=<0 edit: Думаю, я не знаю, как использовать здесь разрывы строк ... каждая команда находится в отдельной строке.

RibeiroBreno 27.11.2014 20:34

вам нужно использовать команду 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

В этой ссылке есть команда «Set / P _MyVar = <MyFilename.txt», которая говорит, что она установит _MyVar на первую строку из MyFilename.txt. Его можно использовать как «myCmd> tmp.txt» с «set / P myVar = <tmp.txt». Но он получит только первую строку вывода, а не весь вывод.

John Meagher 20.09.2008 19:38

Этот ответ для таких новичков, как я

user9599745 22.03.2020 02:16

Пример установки в переменной среды "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

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

John Meagher 20.09.2008 19:35

Скромная команда за за годы накопила несколько интересных возможностей:

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"

Как и в случае с ответом @PabloG, это будет работать только для получения последней строки вывода команды, в данном случае «date / t».

John Meagher 20.09.2008 19:40

Я обнаружил, что ваш ответ работает только тогда, когда я использовал двойные знаки процента, то есть FOR /F "delims = " %%i IN ('date /t') DO set today=%%i

Rabarberski 23.08.2012 17:29

@Rabarberski: Если вы наберете команду for прямо в командной строке, вы используете один %. Если вы используете его в пакетном файле, вы используете %%.

indiv 22.09.2012 09:29

@tardate: Не могли бы вы рассказать, как будет выглядеть скрипт, если команде нужно передать аргумент с %, например: for /f "delims = " %%i in ('date +%F_%H-%M-%S') do set now=%%i

dma_k 04.05.2016 12:17

@dma_k отвечает на 3 года позже, но да, вы используете %%i, однако введенная вами команда недействительна из-за форматирования даты в круглых скобках.

degenerate 23.10.2019 18:20

@degenerate Команда действительна при условии, что используемая команда date исходит от Cygwin. Я согласен, я должен был упомянуть об этом.

dma_k 24.10.2019 08:31

Чтобы получить текущий каталог, вы можете использовать это:

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

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

Есть ли вариант, который будет работать для захвата нескольких строк из команды?

John Meagher 20.09.2008 19:41

Чтобы получить текущий каталог, вы можете использовать echo% CD%

Joe 24.10.2008 12:50
Ответ принят как подходящий

Если вам нужно захватить весь вывод команды, вы можете использовать такой пакет:

@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, разделенные знаком "!".

@John: есть ли в этом практическая польза? Я думаю, вам стоит посмотреть PowerShell или любой другой язык программирования, способный легко выполнять скриптовые задачи (Python, Perl, PHP, Ruby).

Однострочный ответ решит конкретный случай, который у меня есть. Я просто подумал, что есть вариант с несколькими строками (или более простой вариант с одной строкой). Я предполагаю, что возможности файлов bat не так уж велики. Это необходимо для сценариев летучих мышей, обертывающих приложения Java. В основном построение путей к классам.

John Meagher 20.09.2008 21:06

Будьте с этим очень осторожны. GWT также пытался использовать командные файлы для запуска Java с определенными путями к классам, что ужасно провалилось, как только вы попали в каталоги с символами, отличными от ASCII (в этом случае это был мой дом :)). С тех пор они переписали это с помощью VBS.

Joey 09.03.2009 13:44
есть ли в этом практическая польза? Are You kidding? This is used all the time in other shells (all GNU/Linux ones I guess) and it's очень useful.
Piotr Dobrogost 22.10.2011 22:59

@PiotrDobrogost Я думаю, он пытался сказать, что сценарии bash - это ужасный пережиток прошлого (вам нужно использовать для цикла только для захвата вывода программы? Серьезно?), И если вы когда-нибудь дойдете до точки, где вам нужно использовать переменные, вам следует использовать что-то более современное, например PowerShell.

Ajedi32 25.07.2015 23:34

Практическое применение, собственно, есть ... вроде как. Я хочу использовать сценарий PowerShell, чтобы найти конкретный путь к Visual Studio, но то, что мне нужно вне этого пути, - это пакетный файл, который устанавливает кучу переменных env, поэтому я могу вызвать editbin ... Итак, мне нужно найти путь и вернуть его в вызывающий экземпляр cmd, чтобы я мог запустить его там. ... Да, это ужасно, как звучит. Visual Studio иногда заставляет меня плакать. @ Ajedi32 Я думаю, что ты имел в виду, что сценарии партия - это ужасный пережиток прошлого. ;)

jpmc26 22.04.2016 01:29

Если бы команда была простой (без пробелов), вы могли бы выполнить set var=%command%

Sandburg 22.02.2019 11:34

Вы можете записать весь вывод в одну переменную, но строки будут разделены символом по вашему выбору (# в примере ниже) вместо фактического 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=!
    )
)

Если вы ищете решение, представленное в Использование результата команды в качестве аргумента в 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
  • Это вызовет себя с результатом команды CD, так же, как pwd.
  • При извлечении строки по параметрам будет возвращено имя файла / папка.
  • Получите содержимое этой папки и добавьте в filename.txt

[Кредиты]: Спасибо всем остальным ответам и некоторому копанию на странице Команды 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%"

Спасибо за ответ! Хотя фрагмент кода может ответить на вопрос, все же неплохо добавить некоторую дополнительную информацию, например, объяснение и т. д.

j0k 06.10.2012 13:22

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

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

Вы можете использовать %%I как желаемое. Вот так: %%I.

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

К вышеперечисленным решениям хочу добавить замечание:

Все эти синтаксисы работают отлично, ЕСЛИ ВАША КОМАНДА НАЙДЕНА В ПУТИ или ЕСЛИ КОМАНДА ЯВЛЯЕТСЯ 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». Если это не ваш случай, вам нужно найти способ найти путь к вашей команде и изменить каталог по умолчанию на его путь.

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

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

Жиль

Вы можете префикс своей команды с помощью CALL. FOR / F не работает, если в пути есть пробелы

jeb 17.01.2018 20:06

@jeb: БОЛЬШОЕ СПАСИБО! Теперь мой код <CALL "%SOURCEDIR%\FOLDERBROWSE" ... "quoted parameters"> работает отлично.

Gilles Maisonneuve 18.01.2018 01:12

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

результат - "TXT: hola"

Вам следует использовать команду 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 выводом в последнюю строку многострочной команды.

Другие вопросы по теме