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

StackOverflow https://stackoverflow.com/questions/108439

  •  01-07-2019
  •  | 
  •  

Вопрос

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

Это было полезно?

Решение

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

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

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

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

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"

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

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

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

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

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

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

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

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

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

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

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

Если вы ищете решение, представленное в Использовать результат выполнения команды в качестве аргумента в 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%"

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

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

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

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

Gilles

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top