Set output of a command as a variable (with pipes)
Batch FileBatch File Problem Overview
Can you redirect the output of a command to a variable with pipes?
I haven't tried much as I haven't been able to think of anything to try, but I have tried one method (with two variations)...
For example:
echo Hello|set text=
Didn't work, neither did:
echo Hello | set text=
I know you can do it fairly easily with the FOR
command, but I think it would look "nicer" with a pipe.
And if you're wondering, I don't have a specific reason I'm asking this other than I'm curious and I can't find the answer.
Batch File Solutions
Solution 1 - Batch File
Your way can't work for two reasons.
You need to use set /p text=
for setting the variable with user input.
The other problem is the pipe.
A pipe starts two asynchronous cmd.exe instances and after finishing the job both instances are closed.
That's the cause why it seems that the variables are not set, but a small example shows that they are set but the result is lost later.
set myVar=origin
echo Hello | (set /p myVar= & set myVar)
set myVar
Outputs
Hello
origin
Alternatives: You can use the FOR loop to get values into variables or also temp files.
for /f "delims=" %%A in ('echo hello') do set "var=%%A"
echo %var%
or
>output.tmp echo Hello
>>output.tmp echo world
<output.tmp (
set /p line1=
set /p line2=
)
echo %line1%
echo %line2%
Alternative with a macro:
You can use a batch macro, this is a bit like the bash equivalent
@echo off
REM *** Get version string
%$set% versionString="ver"
echo The version is %versionString[0]%
REM *** Get all drive letters
`%$set% driveLetters="wmic logicaldisk get name /value | findstr "Name""
call :ShowVariable driveLetters
The definition of the macro can be found at
SO:Assign output of a program to a variable using a MS batch file
Solution 2 - Batch File
The lack of a Linux-like backtick/backquote facility is a major annoyance of the pre-PowerShell world. Using backquotes via for-loops is not at all cosy. So we need kinda of setvar myvar cmd-line
command.
In my %path%
I have a dir with a number of bins and batches to cope with those Win shortcomings.
One batch I wrote is:
:: setvar varname cmd
:: Set VARNAME to the output of CMD
:: Triple escape pipes, eg:
:: setvar x dir c:\ ^^^| sort
:: -----------------------------
@echo off
SETLOCAL
:: Get command from argument
for /F "tokens=1,*" %%a in ("%*") do set cmd=%%b
:: Get output and set var
for /F "usebackq delims=" %%a in (`%cmd%`) do (
ENDLOCAL
set %1=%%a
)
:: Show results
SETLOCAL EnableDelayedExpansion
echo %1=!%1!
So in your case, you would type:
> setvar text echo Hello
text=Hello
The script informs you of the results, which means you can:
> echo text var is now %text%
text var is now Hello
You can use whatever command:
> setvar text FIND "Jones" names.txt
What if the command you want to pipe to some variable contains itself a pipe?
Triple escape it, ^^^|
:
> setvar text dir c:\ ^^^| find "Win"
Solution 3 - Batch File
THIS DOESN'T USE PIPEs, but requires a single tempfile
I used this to put simplified timestamps into a lowtech daily maintenance batfile
We have already Short-formatted our System-Time to HHmm, (which is 2245 for 10:45PM)
I direct output of Maint-Routines to logfiles with a $DATE%@%TIME% timestamp;
. . . but %TIME% is a long ugly string (ex. 224513.56, for down to the hundredths of a sec)
SOLUTION OVERVIEW:
- Use redirection (">") to send the command "TIME /T" everytime to OVERWRITE a temp-file in the %TEMP% DIRECTORY
- Then use that tempfile as the input to set a new variable (I called it NOW)
- Replace
echo $DATE%@%TIME% blah-blah-blah >> %logfile%
withecho $DATE%@%NOW% blah-blah-blah >> %logfile%
====DIFFERENCE IN OUTPUT:
BEFORE:SUCCESSFUL TIMESYNCH [email protected]
AFTER:SUCCESSFUL TIMESYNCH 29Dec14@2252
ACTUAL CODE:
TIME /T > %TEMP%\DailyTemp.txt SET /p NOW=<%TEMP%\DailyTemp.txt echo $DATE%@%NOW% blah-blah-blah >> %logfile%
AFTERMATH:
All that remains afterwards is the appended logfile, and constantly overwritten tempfile. And if the Tempfile is ever deleted, it will be re-created as necessary.
Solution 4 - Batch File
I find myself a tad amazed at the lack of what I consider the best answer to this question anywhere on the internet. I struggled for many years to find the answer. Many answers online come close, but none really answer it. The real answer is
(cmd
The "secret sauce" being the "closely guarded coveted secret" that "echo." sends a CR/LF (ENTER/new line/0x0D0A). Otherwise, what I am doing here is redirecting the output of the first command to the standard error stream. I then redirect the standard error stream into the standard input stream for the "set /p =" command.
Example:
(echo foo & echo.) >2 & (set /p bar=)<2
Solution 5 - Batch File
In a batch file I usually create a file in the temp directory and append output from a program, then I call it with a variable-name to set that variable. Like this:
:: Create a set_var.cmd file containing: set %1=
set /p="set %%1="<nul>"%temp%\set_var.cmd"
:: Append output from a command
ipconfig | find "IPv4" >> "%temp%\set_var.cmd"
call "%temp%\set_var.cmd" IPAddress
echo %IPAddress%
Solution 6 - Batch File
You can set the output to a temporary file and the read the data from the file after that you can delete the temporary file.
echo %date%>temp.txt
set /p myVarDate= < temp.txt
echo Date is %myVarDate%
del temp.txt
In this variable myVarDate
contains the output of command.