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

<p>я ищу, чтобы получить результат команды в качестве переменной в пакетном скрипте windows (см. <a href="https://stackoverflow.com/questions/58207/using-the-result-of-a-command-as-an-argument-in-bash#58214">как получить результат команды в bash</a> для эквивалентного сценария bash). решение, которое будет работать в .bat-файле, предпочтительнее, но приветствуются и другие распространенные сценарии windows. </p>

<p>если вам нужно захватить весь вывод команды, вы можете использовать такой пакет:</p><pre><code>@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 </code></pre><p>все выходные строки хранятся в var с разделением "!".</p><p>@ джон: есть ли практическое применение для этого? я думаю, вы должны смотреть powershell или любой другой язык программирования, способный легко выполнять задачи сценариев (python, perl, php, ruby)</p>

<p>скромная<strong> для </strong>команда накопила некоторые интересные возможности за эти годы:</p><pre><code>d:\> for /f "delims=" %i in ('date /t') do set today=%i d:\> echo %today% sat 20/09/2008 </code></pre><p>обратите внимание, что <code>"delims="</code> перезаписывает пробел по умолчанию и разделители табуляции, так что выходные данные команды date сожжены все сразу.</p><p>для захвата многострочного вывода он по-прежнему может быть однострочным (используя переменную lf в качестве разделителя в результирующей переменной):</p><pre><code>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% </code></pre><p>для захвата переданного по трубопроводу выражения используйте <code>^|</code>:</p><pre><code>for /f "delims=" %%i in ('svn info . ^| findstr "root:"') do set "url=%%i" </code></pre>

<p>чтобы получить текущий каталог, вы можете использовать это:</p><pre><code>cd > tmpfile set /p myvar= < tmpfile del tmpfile echo test: %myvar% </code></pre><p>он использует временный файл, поэтому он не самый красивый, но он, безусловно, работает! «cd» помещает текущий каталог в «tmpfile», «set» загружает содержимое tmpfile.</p><p>вот решение для нескольких строк с "массивом":</p><pre><code>@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 </code></pre><p>но вы можете захотеть перейти на другую более мощную оболочку или создать приложение для этого. это значительно расширяет возможности пакетных файлов.</p>

<p>вам нужно использовать команду <code>set</code> с параметром <code>/p</code> и направить свой вывод на него . например, см. <a href="http://www.ss64.com/nt/set.html">http://www.ss64.com/nt/set.html</a> . будет работать для cmd, не уверен насчет файлов .bat</p><p>из комментария к этому посту:</p><blockquote> <p>эта ссылка имеет команду "<code>set /p \_myvar=<myfilename.txt</code>", которая говорит, что она установит <code>\_myvar</code> в первую строку из <code>myfilename.txt</code>. это могло быть используется как "<code>mycmd > tmp.txt</code>" с "<code>set /p myvar=<tmp.txt</code>". но это будет только получить первую строку вывода, а не все выходные</p> </blockquote>

<p>пример установки в переменную окружения "v" самого последнего файла </p><pre><code>for /f %i in ('dir *.* /o:d /b') do set v=%i </code></pre><p>в пакетном файле вы должны использовать двойной префикс в переменной цикла:</p><pre><code>for /f %%i in ('dir *.* /o:d /b') do set v=%%i </code></pre>

<p>просто используйте результат команды <code>for</code>. например (внутри командного файла):</p><pre><code>for /f "delims=" %%i in ('dir /b /a-d /od filesa*') do (echo %%i) </code></pre><p>вы можете использовать <code>%%i</code> в качестве значения, которое вы хотите. просто так: <code>%%i</code>.</p><p>и заранее <code>%%i</code> не имеет пробелов или символов cr и может использоваться для сравнения !!</p>

<pre><code>@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%" </code></pre>

<p>если вы ищете решение, представленное в <a href="https://stackoverflow.com/questions/58207/using-the-result-of-a-command-as-an-argument-in-bash">использование результата команды в качестве аргумента в bash?</a> </p><p>тогда вот код:</p><pre><code>@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 </code></pre><ul> <li>это вызовет себя с результатом команды cd, такой же, как pwd.</li> <li>извлечение строки по параметрам вернет имя файла/папки.</li> <li>получить содержимое этой папки и добавить к имени файла .txt</li> </ul><p><strong>[credits]</strong>: благодаря всем остальным ответам и некоторому копанию на <a href="http://www.ss64.com/nt/">windows xp команды</a> page.</p>

<p>вы можете записать все выходные данные в одну переменную, но строки будут разделены символом по вашему выбору (# в приведенном ниже примере) вместо фактического cr-lf.</p><pre><code>@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% </code></pre><p>вторая версия, если вам нужно распечатать содержимое построчно. это использует тот факт, что в dir/b не будет дублированных строк вывода, поэтому в общем случае это может не сработать.</p><pre><code>@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=! ) ) </code></pre>

<p>я хотел бы добавить замечание к вышеупомянутым решениям:</p><p>все эти синтаксисы работают отлично, если ваша команда is найдется в пути, или если команда is, cmdpath без пространств or специальных персонажей.</p><p>но если вы попытаетесь использовать исполняемую команду, расположенную в папке, путь к которой содержит специальные символы, вам потребуется заключить путь к команде в двойные кавычки ("), и тогда синтаксис for/f не будет работать.</p><p>примеры:</p><pre><code>$ for /f "tokens= usebackq" %f in ( ""f:glw7distribsystemshells and scriptingf2ko.defolderbrowse.exe"" hello '"f:glw7distribsystemshells 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. </code></pre><p>или же </p><pre><code>`$ 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. </code></pre><p>в этом случае единственное решение, которое я нашел для использования команды и сохранения ее результата в переменной, - это установить (временно) каталог по умолчанию в каталог самой команды:</p><pre><code>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% </code></pre><p>результат тогда правильный:</p><pre><code>my selected folder: f:\glw7\distrib\system\os install, recovery, vm\ press any key to continue . . . </code></pre><p>конечно, в приведенном выше примере я предполагаю, что мой пакетный скрипт находится в той же папке, что и моя исполняемая команда, так что я могу использовать синтаксис «% ~ d0% ~ p0». если это не ваш случай, вам нужно найти способ найти путь к вашей команде и изменить каталог по умолчанию на его путь.</p><p>nb. для тех, кто интересуется, здесь приведен пример команды (для выбора папки) folderbrowse.exe. я нашел это на веб-сайте f2ko.de ( <a href="http://f2ko.de/en/cmd.php">http://f2ko.de/en/cmd.php</a> ).</p><p>если у кого-то есть лучшее решение для такого рода команд, доступное по сложному пути, я буду очень рад услышать об этом.</p><p>жилль</p>

<p>вы должны использовать команду <code>for</code>, вот пример:</p><pre><code>@echo off rem commands go here exit /b :output for /f "tokens=* useback" %%a in (`%~1`) do set "output=%%a" </code></pre><p>и вы можете использовать <code>call :output "command goes here"</code>, тогда вывод будет в переменной <code>%output%</code>.</p><p><strong> примечание: </strong>если у вас есть вывод команды, который является многострочным, этот инструмент будет <code>set</code> вывод в последнюю строку вашей многострочной команды.</p>

<pre><code>@echo off setlocal enabledelayedexpansion for /f "tokens=1 delims= " %%i in ('echo hola') do ( set txt=%%i ) echo 'txt: %txt%' </code></pre><p>результат «txt: привет»</p>