views:

1726

answers:

8

I'm looking to get the result of a command as a variable in a Windows batch script (see how to get the result of a command in bash for the bash scripting equivalent). A solution that will work in a .bat file is preferred, but other common windows scripting solutions are also welcome.

A: 

Please refer to this http://technet.microsoft.com/en-us/library/bb490982.aspx which explains what you can do with command output.

Jack B Nimble
That article just covers redirection and related topics. It doesn't answer the question of how to take the output of one command and get it into a variable.
John Meagher
A: 

you need to use the SET command with parameter /P and direct your output to it. For example see http://www.ss64.com/nt/set.html. Will work for CMD, not sure about .BAT files

From a comment to this post:

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

Ilya Kochetov
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.
John Meagher
+1  A: 

Example to set in the "V" environment variable the most recent file

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

in a batch file you have to use double prefix in the loop variable:

FOR /F %%I IN ('DIR *.* /O:D /B') DO SET V=%%I
PabloG
I have seen this approach before, but it seems really hacky. It also has the problem that it only will capture the last line of output from the command in the variable.
John Meagher
+1  A: 

The humble for command has accumulated some interesting capabilities over the years:

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

(note that delims= is used to over-write the default space and tab delimiters so that the output of the date command gets gobbled all at once)

To capture multi-line output, it can still essentially be a one-liner (using the variable lf as the delimiter in the resulting variable):

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%
tardate
As with @PabloG's answer, this will only work to get the last line of output from the command, "date /t" in this case.
John Meagher
+1  A: 

To get the current directory, you can use this:

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

It's using a temp-file though, so it's not the most pretty, but it certainly works! 'CD' puts the current directory in 'tmpFile', 'SET' loads the content of tmpFile.

Here is a solution for multiple lines with "array's":

@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

But you might want to consider moving to another more powerful shell or create an application for this stuff. It's stretching the possibilities of the batch files quite a bit.

Evil Activity
Is there a variation that will work to capture multiple lines from the command?
John Meagher
To get the current directory you can use echo %CD%
Joe
+2  A: 

If you have to capture all the command output you can use a batch like this:

@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

All output lines are stored in VAR separated with "!".

@John: is there any practical use for this? I think you should watch PowerShell or any other programming language capable to perform scripting tasks easily (Python, Perl, PHP, Ruby)

PabloG
The single line answer will solve the specific case I have. I just figured there was a multi-line option (or an easier single line option). I guess the capabilities of bat files just aren't that great. The need for it is for bat scripts wrapping Java apps. Building classpaths mainly.
John Meagher
Be very careful with that. GWT also tried to use batch files for starting Java with specific classpaths, which failed horrible as soon as you're getting to directories with non-ASCII characters (in that case it was my home :)). They since rewrote that with VBS.
Joey
+1  A: 

You can capture all output in one variable, but the lines will be separated by a character of your choice (# in the example below) instead of an actual 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%

Second version, if you need to print the contents out line-by-line. This takes advanted of the fact that there won't be duplicate lines of output from "dir /b", so it may not work in the general case.

@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=!
    )
)
Adam Mitz
+1  A: 

If you're looking for the solution provided in Using the result of a command as an argument in bash?

then here is the 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
  • 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]: Thanks to all the other answers and some digging on the Windows XP commands page.

Gustavo Carreno