Copy command output result to variable batch - windows

So I'm trying to copy a local file to my network using batch scripting and would like to be able to get a result to know if the process completed properly.
My code is below:
#echo off
set locatie_folder=G:\Info\instructiuni.mht
for /f "tokens=1,2 delims= " %%a in (IP.txt) do (
copy %locatie_folder% "\\%%a\vsr">> temp.tmp
set /p VAR=<temp.tmp
echo %%b %VAR%
del temp.tmp
)
pause
exit
My IP.txt file looks like so:
10.117.14.10 100-01
10.117.14.11 100-02
10.117.14.12 100-03
First is the IP and second is a dedicated name for that IP in the network.
I need to output something like
100-01 1 file(s) copied.
100-02 0 file(s) copied.
100-03 1 file(s) copied.
Now my problem is that for some reason the variable VAR is not getting me the status "0 file(s) copied." or "1 file(s) copied." while reading even if it writes properly in the temp.tmp file.
What am I doing wrong here?

You need to enable delayed expansion for getting the new value of VAR, because you are setting and reading it within a block of code (the for loop). The immediate %VAR% expansion always returns the value when the entire block of code is parsed; with delayed !VAR! expansion, you will get the updated value.
Try this:
#echo off
setlocal EnableDelayedExpansion
set "locatie_folder=G:\Info\instructiuni.mht"
for /F "usebackq tokens=1,2 delims= " %%A in ("IP.txt") do (
> "temp.tmp" copy "%locatie_folder%" "\\%%~A\vsr"
< "temp.tmp" set /P VAR=
echo "%%~B" !VAR!
del "temp.tmp"
)
pause
endlocal
exit /B
You can make it all even simpler though, without using a temporary file, when you let another for /F loop capture the output of the copy command:
#echo off
set "locatie_folder=G:\Info\instructiuni.mht"
for /F "usebackq tokens=1,2 delims= " %%A in ("IP.txt") do (
for /F "delims=" %%X in ('copy "%locatie_folder%" "\\%%~A\vsr"') do (
echo "%%~B" %%X
)
)
pause
exit /B

Put your COPY command inside a FOR /F command to capture the verbose output to a variable.
Something like this.
for /F "tokens=* delims= " %%G in ('copy temp.txt C:\temp\') do echo %%b %%G
Edit: with your exact code.
#echo off
set locatie_folder=G:\Info\instructiuni.mht
for /f "tokens=1,2 delims= " %%a in (IP.txt) do (
for /F "tokens=* delims= " %%G in ('copy %locatie_folder% "\\%%a\vsr"') do echo %%b %%G
)
pause
exit

Related

How to extract the last word from the last line of a TXT file through a batch script

I am trying to extract the last word from the last line of a txt file.
The result I want is just Cup$2!.
This is what I tried:
#echo off
SetLocal EnableDelayedExpansion
set L=1
for /F "tokens=2 delims=" %%a in (corner.txt) do (
set line=%%a
if !L!==7 set Line7=%%a
set /a L=!L!+1
)
echo The word is %Line7%
pause
The result I'm getting is The word is.
What should I edit to get the above result?
Get line count.
for /f "tokens=3*" %%i in ('find /c /v /n /i"" corner.txt') do set /a v=%%i-1
Then get the last values from 7-th word of the last line:
for /f "tokens=7*" %%a in ('more corner.txt +%v%') do set "String="%%b""
Variable %String% keeps the values framed by double quotes: Cup&2!/Cup$2!
If you use / as delimiter you can get last value:
for /f "delims=/ tokens=2*" %%a in (%String%) do #echo %%a
Here's a quick example of how you could capture the substring you require, from reading your code, i.e. the last substring on the seventh line:
#Echo Off
SetLocal EnableExtensions DisableDelayedExpansion
Set "var="
For /F UseBackQ^ Skip^=7^ Delims^=^ EOL^= %%G In ("corner.txt") Do Set "var=%%~nxG" & GoTo Next
If Not Defined var GoTo EndIt
:Next
SetLocal EnableDelayedExpansion
Echo The word is !var!
EndLocal
:EndIt
Echo Press any key to close . . .
Pause 1>NUL
EndLocal
Exit /B
If however, as your question title and body asks, you want the last substring of the last line, it's a little bit simpler:
#Echo Off
SetLocal EnableExtensions DisableDelayedExpansion
Set "var="
For /F UseBackQ^ Delims^=^ EOL^= %%G In ("corner.txt") Do Set "var=%%~nxG"
If Not Defined var GoTo EndIt
SetLocal EnableDelayedExpansion
Echo The word is !var!
EndLocal
:EndIt
Echo Press any key to close . . .
Pause 1>NUL
EndLocal
Exit /B
I will not however be explaining any of it, please use the search facility at the top of the page, and the output from the built in help for each of the commands I have used.
Parsing strings in batch files is never ideal but this seems to work:
#echo off
setlocal ENABLEEXTENSIONS DISABLEDELAYEDEXPANSION
echo.line 1 > "%temp%\SO_Test.txt"
echo. >> "%temp%\SO_Test.txt"
echo.foo^&bar!baz hello/world Cup^&2!/Cup$2!>> "%temp%\SO_Test.txt"
goto start
:start
set "line="
for /F "usebackq delims=" %%a in ("%temp%\SO_Test.txt") do #set line=%%a
:word
set "b="
rem Delims is slash, tab, space and the order is important
for /F "tokens=1,* delims=/ " %%A in ("%line%") do (
set "line=%%A"
set "b=%%B"
)
if not "%b%" == "" (
set "line=%b%"
goto word
)
echo.Last word is "%line%"
#ECHO OFF
SETLOCAL
rem The following settings for the source directory, destination directory, target directory,
rem batch directory, filenames, output filename and temporary filename [if shown] are names
rem that I use for testing and deliberately include names which include spaces to make sure
rem that the process works using such names. These will need to be changed to suit your situation.
SET "sourcedir=u:\your files"
SET "filename1=%sourcedir%\q70761955.txt"
SET "amper=&"
FOR /f "usebackq delims=" %%b IN ("%filename1%") DO SET "lastword=%%b"
:: Replace ampersands with spaces, then slashes with spaces
CALL SET "lastword=%%lastword:%amper%= %%"
SET "lastword=%lastword:/= %"
FOR %%b IN (%lastword%) DO SET "lastword=%%b"
ECHO last "word" is -^>%lastword%^<-
GOTO :EOF
Read each line of the file, retaining the last-read line in lastword.
Replace each "delimiter" character (& and / are implied in the question. Others - no information.)
Select the last "word" in the last line.
You would need to change the value assigned to sourcedir to suit your circumstances. The listing uses a setting that suits my system.
I deliberately include spaces in names to ensure that the spaces are processed correctly.
I used a file named q70761955.txt containing your data for my testing.
You could use this in a batch-file run by cmd on windows.
FOR /F "delims=" %%A IN ('powershell -NoLogo -NoProfile -Command ^
"((Get-Content -Path 'corner.txt' -Last 1) -split '[\s*/]')[-1]"') DO (SET "LINE7=%%A")
ECHO %LINE7%
If the script were written in PowerShell instead of cmd language, it could be a one-liner.
$Line7 = ((Get-Content -Path 'corner.txt' -Last 1) -split '[\s*/]')[-1]

How to Store Dir and findStr result in variable in batch file [duplicate]

This question already has answers here:
Assign output of a program to a variable using a MS batch file
(12 answers)
Closed 9 months ago.
Is it possible to set a statement's output of a batch file to a variable, for example:
findstr testing > %VARIABLE%
echo %VARIABLE%
FOR /F "tokens=* USEBACKQ" %%F IN (`command`) DO (
SET var=%%F
)
ECHO %var%
I always use the USEBACKQ so that if you have a string to insert or a long file name, you can use your double quotes without screwing up the command.
Now if your output will contain multiple lines, you can do this
SETLOCAL ENABLEDELAYEDEXPANSION
SET count=1
FOR /F "tokens=* USEBACKQ" %%F IN (`command`) DO (
SET var!count!=%%F
SET /a count=!count!+1
)
ECHO %var1%
ECHO %var2%
ECHO %var3%
ENDLOCAL
In a single line:
FOR /F "tokens=*" %%g IN ('your command') do (SET VAR=%%g)
The command output will be set in %g then in VAR.
More information here: https://ss64.com/nt/for_cmd.html
I found this thread on that there Interweb thing. Boils down to:
#echo off
setlocal enableextensions
for /f "tokens=*" %%a in (
'VER'
) do (
set myvar=%%a
)
echo/%%myvar%%=%myvar%
pause
endlocal
You can also redirect the output of a command to a temporary file, and then put the contents of that temporary file into your variable, likesuchashereby. It doesn't work with multiline input though.
cmd > tmpFile
set /p myvar= < tmpFile
del tmpFile
Credit to the thread on Tom's Hardware.
If you don't want to output to a temp file and then read into a variable, this code stores result of command direct into a variable:
FOR /F %i IN ('findstr testing') DO set VARIABLE=%i
echo %VARIABLE%
If you want to enclose search string in double quotes:
FOR /F %i IN ('findstr "testing"') DO set VARIABLE=%i
If you want to store this code in a batch file, add an extra % symbol:
FOR /F %%i IN ('findstr "testing"') DO set VARIABLE=%%i
A useful example to count the number of files in a directory & store in a variable:
(illustrates piping)
FOR /F %i IN ('dir /b /a-d "%cd%" ^| find /v /c "?"') DO set /a count=%i
Note the use of single quotes instead of double quotes " or grave accent ` in the command brackets. This is cleaner alternative to delims, tokens or usebackq in for loop.
Update 27/8/2021:
Another method is to set errorlevel variable, although many would discourage setting errorlevel on large scripts or when new to cmd flavor of the installed OS variant.
This method works where (return) value to be stored is a 32-bit integer.
eg.
to count the number of files in a directory & store in a variable called errorlevel:
(dir /b /a-d ^| find /v /c "?") | (set /p myVar=& cmd /c exit /b %myVar%)
echo %errorlevel%
81
set /a %errorlevel%+1
82
REM Note: Win CMD arithmetic limit: 2147483647 (32-bit integers)
REM ie. an overflow would continue count at -2147483648
REM and reset again after reaching 2147483647
REM See tests below:
cmd /c exit /b 2147483647
echo %errorlevel%
2147483647
cmd /c exit /b 2147483648
echo %errorlevel%
-2147483648
cmd /c exit /b 2147483649
echo %errorlevel%
-2147483647
Above method can be modified to return encoded strings to be decoded in parent process (within 32 bit limitation).
A 3rd illustration, although of limited use (because the variable is set in child process, not parent) is:
(dir /b /a-d ^| find /v /c "?") | (set /p myVar=& set myVar)
In this case the value of myVar is set to the number of files in the directory
Tested on Win 10 CMD.
To read a file...
set /P Variable=<File.txt
To Write a file
#echo %DataToWrite%>File.txt
note; having spaces before the <> character causes a space to be added at the end of the variable, also
To add to a file,like a logger program,
First make a file with a single enter key in it called e.txt
set /P Data=<log0.log
set /P Ekey=<e.txt
#echo %Data%%Ekey%%NewData%>log0.txt
your log will look like this
Entry1
Entry2
and so on
Anyways a couple useful things
These answers were all so close to the answer that I needed. This is an attempt to expand on them.
In a Batch file
If you're running from within a .bat file and you want a single line that allows you to export a complicated command like jq -r ".Credentials.AccessKeyId" c:\temp\mfa-getCreds.json to a variable named AWS_ACCESS_KEY then you want this:
FOR /F "tokens=* USEBACKQ" %%g IN (`jq -r ".Credentials.AccessKeyId" c:\temp\mfa-getCreds.json`) do (SET "AWS_ACCESS_KEY=%%g")
On the Command Line
If you're at the C:\ prompt you want a single line that allows you to run a complicated command like jq -r ".Credentials.AccessKeyId" c:\temp\mfa-getCreds.json to a variable named AWS_ACCESS_KEY then you want this:
FOR /F "tokens=* USEBACKQ" %g IN (`jq -r ".Credentials.AccessKeyId" c:\temp\mfa-getCreds.json`) do (SET "AWS_ACCESS_KEY=%g")
Explanation
The only difference between the two answers above is that on the command line, you use a single % in your variable. In a batch file, you have to double up on the percentage signs (%%).
Since the command includes colons, quotes, and parentheses, you need to include the USEBACKQ line in the options so that you can use backquotes to specify the command to run and then all kinds of funny characters inside of it.
Some notes and some tricks.
The 'official' way to assign result to a variable is with FOR /F though in the other answers is shown how a temporary file can be used also.
For command processing FOR command has two forms depending if the usebackq option is used. In the all examples below the whole output is used without splitting it.
FOR /f "tokens=* delims=" %%A in ('whoami') do #set "I-Am=%%A"
FOR /f "usebackq tokens=* delims=" %%A in (`whoami`) do #set "I-Am=%%A"
and if used directly in the console:
FOR /f "tokens=* delims=" %A in ('whoami') do set "I-Am=%A"
FOR /f "usebackq tokens=* delims=" %A in (`whoami`) do set "I-Am=%A"
%%A is a temporary variable available only on the FOR command context and is called token.The two forms can be useful in case when you are dealing with arguments containing specific quotes. It is especially useful with REPL interfaces of other languages or WMIC.
Though in both cases the expression can be put in double quotes and it still be processed.
Here's an example with python (it is possible to transition the expression in the brackets on a separate line which is used for easier reading):
#echo off
for /f "tokens=* delims=" %%a in (
'"python -c ""print("""Message from python""")"""'
) do (
echo processed message from python: "%%a"
)
To use an assigned variable in the same FOR block check also the DELAYED EXPANSION
And some tricks
To save yourself from writing all the arguments for the FOR command you can use MACRO for assigning the result to variable:
#echo off
::::: ---- defining the assign macro ---- ::::::::
setlocal DisableDelayedExpansion
(set LF=^
%=EMPTY=%
)
set ^"\n=^^^%LF%%LF%^%LF%%LF%^^"
::set argv=Empty
set assign=for /L %%n in (1 1 2) do ( %\n%
if %%n==2 (%\n%
setlocal enableDelayedExpansion%\n%
for /F "tokens=1,2 delims=," %%A in ("!argv!") do (%\n%
for /f "tokens=* delims=" %%# in ('%%~A') do endlocal^&set "%%~B=%%#" %\n%
) %\n%
) %\n%
) ^& set argv=,
::::: -------- ::::::::
:::EXAMPLE
%assign% "WHOAMI /LOGONID",result
echo %result%
the first argument to the macro is the command and the second the name of the variable we want to use and both are separated by , (comma). Though this is suitable only for straight forward scenarios.
If we want a similar macro for the console we can use DOSKEY
doskey assign=for /f "tokens=1,2 delims=," %a in ("$*") do #for /f "tokens=* delims=" %# in ('"%a"') do #set "%b=%#"
rem -- example --
assign WHOAMI /LOGONID,my-id
echo %my-id%
DOSKEY does accept double quotes as enclosion for arguments so this also is useful for more simple scenarios.
FOR also works well with pipes which can be used for chaining commands (though it is not so good for assigning a variable.
hostname |for /f "tokens=* delims=" %%# in ('more') do #(ping %%#)
Which also can be beautified with macros:
#echo off
:: --- defining chain command macros ---
set "result-as-[arg]:=|for /f "tokens=* delims=" %%# in ('more') do #("
set "[arg]= %%#)"
::: -------------------------- :::
::Example:
hostname %result-as-[arg]:% ping %[arg]%
And for completnes macros for the temp file approach (no doskey definition ,but it also can be easy done.If you have a SSD this wont be so slow):
#echo off
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
set "[[=>"#" 2>&1&set/p "&set "]]==<# & del /q # >nul 2>&1"
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
chcp %[[%code-page%]]%
echo ~~%code-page%~~
whoami %[[%its-me%]]%
echo ##%its-me%##
For /f with another macro:
::::::::::::::::::::::::::::::::::::::::::::::::::
;;set "{{=for /f "tokens=* delims=" %%# in ('" &::
;;set "--=') do #set "" &::
;;set "}}==%%#"" &::
::::::::::::::::::::::::::::::::::::::::::::::::::
:: --examples
::assigning ver output to %win-ver% variable
%{{% ver %--%win-ver%}}%
echo 3: %win-ver%
::assigning hostname output to %my-host% variable
%{{% hostname %--%my-host%}}%
echo 4: %my-host%
cd %windir%\system32\inetsrv
#echo off
for /F "tokens=* USEBACKQ" %%x in (
`appcmd list apppool /text:name`
) do (
echo|set /p= "%%x - " /text:name & appcmd.exe list apppool "%%x" /text:processModel.identityType
)
echo %date% & echo %time%
pause
I most cases, creating a temporary file named after your variable name might be acceptable. (as you are probably using meaningful variables name...)
Here, my variable name is SSH_PAGEANT_AUTH_SOCK
dir /w "\\.\pipe\\"|find "pageant" > %temp%\SSH_PAGEANT_AUTH_SOCK && set /P SSH_PAGEANT_AUTH_SOCK=<%temp%\SSH_PAGEANT_AUTH_SOCK

How to store python version in a variable inside .bat file in an easy way? [duplicate]

This question already has answers here:
Assign output of a program to a variable using a MS batch file
(12 answers)
Closed 9 months ago.
Is it possible to set a statement's output of a batch file to a variable, for example:
findstr testing > %VARIABLE%
echo %VARIABLE%
FOR /F "tokens=* USEBACKQ" %%F IN (`command`) DO (
SET var=%%F
)
ECHO %var%
I always use the USEBACKQ so that if you have a string to insert or a long file name, you can use your double quotes without screwing up the command.
Now if your output will contain multiple lines, you can do this
SETLOCAL ENABLEDELAYEDEXPANSION
SET count=1
FOR /F "tokens=* USEBACKQ" %%F IN (`command`) DO (
SET var!count!=%%F
SET /a count=!count!+1
)
ECHO %var1%
ECHO %var2%
ECHO %var3%
ENDLOCAL
In a single line:
FOR /F "tokens=*" %%g IN ('your command') do (SET VAR=%%g)
The command output will be set in %g then in VAR.
More information here: https://ss64.com/nt/for_cmd.html
I found this thread on that there Interweb thing. Boils down to:
#echo off
setlocal enableextensions
for /f "tokens=*" %%a in (
'VER'
) do (
set myvar=%%a
)
echo/%%myvar%%=%myvar%
pause
endlocal
You can also redirect the output of a command to a temporary file, and then put the contents of that temporary file into your variable, likesuchashereby. It doesn't work with multiline input though.
cmd > tmpFile
set /p myvar= < tmpFile
del tmpFile
Credit to the thread on Tom's Hardware.
If you don't want to output to a temp file and then read into a variable, this code stores result of command direct into a variable:
FOR /F %i IN ('findstr testing') DO set VARIABLE=%i
echo %VARIABLE%
If you want to enclose search string in double quotes:
FOR /F %i IN ('findstr "testing"') DO set VARIABLE=%i
If you want to store this code in a batch file, add an extra % symbol:
FOR /F %%i IN ('findstr "testing"') DO set VARIABLE=%%i
A useful example to count the number of files in a directory & store in a variable:
(illustrates piping)
FOR /F %i IN ('dir /b /a-d "%cd%" ^| find /v /c "?"') DO set /a count=%i
Note the use of single quotes instead of double quotes " or grave accent ` in the command brackets. This is cleaner alternative to delims, tokens or usebackq in for loop.
Update 27/8/2021:
Another method is to set errorlevel variable, although many would discourage setting errorlevel on large scripts or when new to cmd flavor of the installed OS variant.
This method works where (return) value to be stored is a 32-bit integer.
eg.
to count the number of files in a directory & store in a variable called errorlevel:
(dir /b /a-d ^| find /v /c "?") | (set /p myVar=& cmd /c exit /b %myVar%)
echo %errorlevel%
81
set /a %errorlevel%+1
82
REM Note: Win CMD arithmetic limit: 2147483647 (32-bit integers)
REM ie. an overflow would continue count at -2147483648
REM and reset again after reaching 2147483647
REM See tests below:
cmd /c exit /b 2147483647
echo %errorlevel%
2147483647
cmd /c exit /b 2147483648
echo %errorlevel%
-2147483648
cmd /c exit /b 2147483649
echo %errorlevel%
-2147483647
Above method can be modified to return encoded strings to be decoded in parent process (within 32 bit limitation).
A 3rd illustration, although of limited use (because the variable is set in child process, not parent) is:
(dir /b /a-d ^| find /v /c "?") | (set /p myVar=& set myVar)
In this case the value of myVar is set to the number of files in the directory
Tested on Win 10 CMD.
To read a file...
set /P Variable=<File.txt
To Write a file
#echo %DataToWrite%>File.txt
note; having spaces before the <> character causes a space to be added at the end of the variable, also
To add to a file,like a logger program,
First make a file with a single enter key in it called e.txt
set /P Data=<log0.log
set /P Ekey=<e.txt
#echo %Data%%Ekey%%NewData%>log0.txt
your log will look like this
Entry1
Entry2
and so on
Anyways a couple useful things
These answers were all so close to the answer that I needed. This is an attempt to expand on them.
In a Batch file
If you're running from within a .bat file and you want a single line that allows you to export a complicated command like jq -r ".Credentials.AccessKeyId" c:\temp\mfa-getCreds.json to a variable named AWS_ACCESS_KEY then you want this:
FOR /F "tokens=* USEBACKQ" %%g IN (`jq -r ".Credentials.AccessKeyId" c:\temp\mfa-getCreds.json`) do (SET "AWS_ACCESS_KEY=%%g")
On the Command Line
If you're at the C:\ prompt you want a single line that allows you to run a complicated command like jq -r ".Credentials.AccessKeyId" c:\temp\mfa-getCreds.json to a variable named AWS_ACCESS_KEY then you want this:
FOR /F "tokens=* USEBACKQ" %g IN (`jq -r ".Credentials.AccessKeyId" c:\temp\mfa-getCreds.json`) do (SET "AWS_ACCESS_KEY=%g")
Explanation
The only difference between the two answers above is that on the command line, you use a single % in your variable. In a batch file, you have to double up on the percentage signs (%%).
Since the command includes colons, quotes, and parentheses, you need to include the USEBACKQ line in the options so that you can use backquotes to specify the command to run and then all kinds of funny characters inside of it.
Some notes and some tricks.
The 'official' way to assign result to a variable is with FOR /F though in the other answers is shown how a temporary file can be used also.
For command processing FOR command has two forms depending if the usebackq option is used. In the all examples below the whole output is used without splitting it.
FOR /f "tokens=* delims=" %%A in ('whoami') do #set "I-Am=%%A"
FOR /f "usebackq tokens=* delims=" %%A in (`whoami`) do #set "I-Am=%%A"
and if used directly in the console:
FOR /f "tokens=* delims=" %A in ('whoami') do set "I-Am=%A"
FOR /f "usebackq tokens=* delims=" %A in (`whoami`) do set "I-Am=%A"
%%A is a temporary variable available only on the FOR command context and is called token.The two forms can be useful in case when you are dealing with arguments containing specific quotes. It is especially useful with REPL interfaces of other languages or WMIC.
Though in both cases the expression can be put in double quotes and it still be processed.
Here's an example with python (it is possible to transition the expression in the brackets on a separate line which is used for easier reading):
#echo off
for /f "tokens=* delims=" %%a in (
'"python -c ""print("""Message from python""")"""'
) do (
echo processed message from python: "%%a"
)
To use an assigned variable in the same FOR block check also the DELAYED EXPANSION
And some tricks
To save yourself from writing all the arguments for the FOR command you can use MACRO for assigning the result to variable:
#echo off
::::: ---- defining the assign macro ---- ::::::::
setlocal DisableDelayedExpansion
(set LF=^
%=EMPTY=%
)
set ^"\n=^^^%LF%%LF%^%LF%%LF%^^"
::set argv=Empty
set assign=for /L %%n in (1 1 2) do ( %\n%
if %%n==2 (%\n%
setlocal enableDelayedExpansion%\n%
for /F "tokens=1,2 delims=," %%A in ("!argv!") do (%\n%
for /f "tokens=* delims=" %%# in ('%%~A') do endlocal^&set "%%~B=%%#" %\n%
) %\n%
) %\n%
) ^& set argv=,
::::: -------- ::::::::
:::EXAMPLE
%assign% "WHOAMI /LOGONID",result
echo %result%
the first argument to the macro is the command and the second the name of the variable we want to use and both are separated by , (comma). Though this is suitable only for straight forward scenarios.
If we want a similar macro for the console we can use DOSKEY
doskey assign=for /f "tokens=1,2 delims=," %a in ("$*") do #for /f "tokens=* delims=" %# in ('"%a"') do #set "%b=%#"
rem -- example --
assign WHOAMI /LOGONID,my-id
echo %my-id%
DOSKEY does accept double quotes as enclosion for arguments so this also is useful for more simple scenarios.
FOR also works well with pipes which can be used for chaining commands (though it is not so good for assigning a variable.
hostname |for /f "tokens=* delims=" %%# in ('more') do #(ping %%#)
Which also can be beautified with macros:
#echo off
:: --- defining chain command macros ---
set "result-as-[arg]:=|for /f "tokens=* delims=" %%# in ('more') do #("
set "[arg]= %%#)"
::: -------------------------- :::
::Example:
hostname %result-as-[arg]:% ping %[arg]%
And for completnes macros for the temp file approach (no doskey definition ,but it also can be easy done.If you have a SSD this wont be so slow):
#echo off
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
set "[[=>"#" 2>&1&set/p "&set "]]==<# & del /q # >nul 2>&1"
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
chcp %[[%code-page%]]%
echo ~~%code-page%~~
whoami %[[%its-me%]]%
echo ##%its-me%##
For /f with another macro:
::::::::::::::::::::::::::::::::::::::::::::::::::
;;set "{{=for /f "tokens=* delims=" %%# in ('" &::
;;set "--=') do #set "" &::
;;set "}}==%%#"" &::
::::::::::::::::::::::::::::::::::::::::::::::::::
:: --examples
::assigning ver output to %win-ver% variable
%{{% ver %--%win-ver%}}%
echo 3: %win-ver%
::assigning hostname output to %my-host% variable
%{{% hostname %--%my-host%}}%
echo 4: %my-host%
cd %windir%\system32\inetsrv
#echo off
for /F "tokens=* USEBACKQ" %%x in (
`appcmd list apppool /text:name`
) do (
echo|set /p= "%%x - " /text:name & appcmd.exe list apppool "%%x" /text:processModel.identityType
)
echo %date% & echo %time%
pause
I most cases, creating a temporary file named after your variable name might be acceptable. (as you are probably using meaningful variables name...)
Here, my variable name is SSH_PAGEANT_AUTH_SOCK
dir /w "\\.\pipe\\"|find "pageant" > %temp%\SSH_PAGEANT_AUTH_SOCK && set /P SSH_PAGEANT_AUTH_SOCK=<%temp%\SSH_PAGEANT_AUTH_SOCK

Windows Shell Script to load csv into variables

I am trying to use Windows built-in shell script to load this file:
hostname1,host_specific_file1
hostname2,host_specific_file2
hostname3,host_specific_file3
.
.
.
Like this:
for /f "tokens=1,2* delims=," %%i in (host-info.txt) do set clientName=%%i; set fileLoc=%%j
Which doesn't work but I want it to go like this:
:loop
For each line, Set the current_hostname=hostnamex and Set the current_file=host_specific_filex
And THEN
DO STUFF
Goto next line, Goto loop
Is there a method for doing this? I can't get my script wrapped around the "Goto next line" or "Handle one line at a time" concept.
Thanks,
Chris
You can;
echo off
setlocal enabledelayedexpansion
for /f "tokens=1,2* delims=," %%i in (host-info.txt) do (
set clientName=%%i
set fileLoc=%%j
call:handler
)
goto:eof
:handler
echo client name is !clientName! location is !fileLoc!
goto:eof
Or Using %n notation;
echo off
setlocal enabledelayedexpansion
for /f "tokens=1,2* delims=," %%i in (host-info.txt) do call:handler %%i %%j
goto:eof
:handler
echo client name is %1 location is %2 ...

How to set commands output as a variable in a batch file [duplicate]

This question already has answers here:
Assign output of a program to a variable using a MS batch file
(12 answers)
Closed 9 months ago.
Is it possible to set a statement's output of a batch file to a variable, for example:
findstr testing > %VARIABLE%
echo %VARIABLE%
FOR /F "tokens=* USEBACKQ" %%F IN (`command`) DO (
SET var=%%F
)
ECHO %var%
I always use the USEBACKQ so that if you have a string to insert or a long file name, you can use your double quotes without screwing up the command.
Now if your output will contain multiple lines, you can do this
SETLOCAL ENABLEDELAYEDEXPANSION
SET count=1
FOR /F "tokens=* USEBACKQ" %%F IN (`command`) DO (
SET var!count!=%%F
SET /a count=!count!+1
)
ECHO %var1%
ECHO %var2%
ECHO %var3%
ENDLOCAL
In a single line:
FOR /F "tokens=*" %%g IN ('your command') do (SET VAR=%%g)
The command output will be set in %g then in VAR.
More information here: https://ss64.com/nt/for_cmd.html
I found this thread on that there Interweb thing. Boils down to:
#echo off
setlocal enableextensions
for /f "tokens=*" %%a in (
'VER'
) do (
set myvar=%%a
)
echo/%%myvar%%=%myvar%
pause
endlocal
You can also redirect the output of a command to a temporary file, and then put the contents of that temporary file into your variable, likesuchashereby. It doesn't work with multiline input though.
cmd > tmpFile
set /p myvar= < tmpFile
del tmpFile
Credit to the thread on Tom's Hardware.
If you don't want to output to a temp file and then read into a variable, this code stores result of command direct into a variable:
FOR /F %i IN ('findstr testing') DO set VARIABLE=%i
echo %VARIABLE%
If you want to enclose search string in double quotes:
FOR /F %i IN ('findstr "testing"') DO set VARIABLE=%i
If you want to store this code in a batch file, add an extra % symbol:
FOR /F %%i IN ('findstr "testing"') DO set VARIABLE=%%i
A useful example to count the number of files in a directory & store in a variable:
(illustrates piping)
FOR /F %i IN ('dir /b /a-d "%cd%" ^| find /v /c "?"') DO set /a count=%i
Note the use of single quotes instead of double quotes " or grave accent ` in the command brackets. This is cleaner alternative to delims, tokens or usebackq in for loop.
Update 27/8/2021:
Another method is to set errorlevel variable, although many would discourage setting errorlevel on large scripts or when new to cmd flavor of the installed OS variant.
This method works where (return) value to be stored is a 32-bit integer.
eg.
to count the number of files in a directory & store in a variable called errorlevel:
(dir /b /a-d ^| find /v /c "?") | (set /p myVar=& cmd /c exit /b %myVar%)
echo %errorlevel%
81
set /a %errorlevel%+1
82
REM Note: Win CMD arithmetic limit: 2147483647 (32-bit integers)
REM ie. an overflow would continue count at -2147483648
REM and reset again after reaching 2147483647
REM See tests below:
cmd /c exit /b 2147483647
echo %errorlevel%
2147483647
cmd /c exit /b 2147483648
echo %errorlevel%
-2147483648
cmd /c exit /b 2147483649
echo %errorlevel%
-2147483647
Above method can be modified to return encoded strings to be decoded in parent process (within 32 bit limitation).
A 3rd illustration, although of limited use (because the variable is set in child process, not parent) is:
(dir /b /a-d ^| find /v /c "?") | (set /p myVar=& set myVar)
In this case the value of myVar is set to the number of files in the directory
Tested on Win 10 CMD.
To read a file...
set /P Variable=<File.txt
To Write a file
#echo %DataToWrite%>File.txt
note; having spaces before the <> character causes a space to be added at the end of the variable, also
To add to a file,like a logger program,
First make a file with a single enter key in it called e.txt
set /P Data=<log0.log
set /P Ekey=<e.txt
#echo %Data%%Ekey%%NewData%>log0.txt
your log will look like this
Entry1
Entry2
and so on
Anyways a couple useful things
These answers were all so close to the answer that I needed. This is an attempt to expand on them.
In a Batch file
If you're running from within a .bat file and you want a single line that allows you to export a complicated command like jq -r ".Credentials.AccessKeyId" c:\temp\mfa-getCreds.json to a variable named AWS_ACCESS_KEY then you want this:
FOR /F "tokens=* USEBACKQ" %%g IN (`jq -r ".Credentials.AccessKeyId" c:\temp\mfa-getCreds.json`) do (SET "AWS_ACCESS_KEY=%%g")
On the Command Line
If you're at the C:\ prompt you want a single line that allows you to run a complicated command like jq -r ".Credentials.AccessKeyId" c:\temp\mfa-getCreds.json to a variable named AWS_ACCESS_KEY then you want this:
FOR /F "tokens=* USEBACKQ" %g IN (`jq -r ".Credentials.AccessKeyId" c:\temp\mfa-getCreds.json`) do (SET "AWS_ACCESS_KEY=%g")
Explanation
The only difference between the two answers above is that on the command line, you use a single % in your variable. In a batch file, you have to double up on the percentage signs (%%).
Since the command includes colons, quotes, and parentheses, you need to include the USEBACKQ line in the options so that you can use backquotes to specify the command to run and then all kinds of funny characters inside of it.
Some notes and some tricks.
The 'official' way to assign result to a variable is with FOR /F though in the other answers is shown how a temporary file can be used also.
For command processing FOR command has two forms depending if the usebackq option is used. In the all examples below the whole output is used without splitting it.
FOR /f "tokens=* delims=" %%A in ('whoami') do #set "I-Am=%%A"
FOR /f "usebackq tokens=* delims=" %%A in (`whoami`) do #set "I-Am=%%A"
and if used directly in the console:
FOR /f "tokens=* delims=" %A in ('whoami') do set "I-Am=%A"
FOR /f "usebackq tokens=* delims=" %A in (`whoami`) do set "I-Am=%A"
%%A is a temporary variable available only on the FOR command context and is called token.The two forms can be useful in case when you are dealing with arguments containing specific quotes. It is especially useful with REPL interfaces of other languages or WMIC.
Though in both cases the expression can be put in double quotes and it still be processed.
Here's an example with python (it is possible to transition the expression in the brackets on a separate line which is used for easier reading):
#echo off
for /f "tokens=* delims=" %%a in (
'"python -c ""print("""Message from python""")"""'
) do (
echo processed message from python: "%%a"
)
To use an assigned variable in the same FOR block check also the DELAYED EXPANSION
And some tricks
To save yourself from writing all the arguments for the FOR command you can use MACRO for assigning the result to variable:
#echo off
::::: ---- defining the assign macro ---- ::::::::
setlocal DisableDelayedExpansion
(set LF=^
%=EMPTY=%
)
set ^"\n=^^^%LF%%LF%^%LF%%LF%^^"
::set argv=Empty
set assign=for /L %%n in (1 1 2) do ( %\n%
if %%n==2 (%\n%
setlocal enableDelayedExpansion%\n%
for /F "tokens=1,2 delims=," %%A in ("!argv!") do (%\n%
for /f "tokens=* delims=" %%# in ('%%~A') do endlocal^&set "%%~B=%%#" %\n%
) %\n%
) %\n%
) ^& set argv=,
::::: -------- ::::::::
:::EXAMPLE
%assign% "WHOAMI /LOGONID",result
echo %result%
the first argument to the macro is the command and the second the name of the variable we want to use and both are separated by , (comma). Though this is suitable only for straight forward scenarios.
If we want a similar macro for the console we can use DOSKEY
doskey assign=for /f "tokens=1,2 delims=," %a in ("$*") do #for /f "tokens=* delims=" %# in ('"%a"') do #set "%b=%#"
rem -- example --
assign WHOAMI /LOGONID,my-id
echo %my-id%
DOSKEY does accept double quotes as enclosion for arguments so this also is useful for more simple scenarios.
FOR also works well with pipes which can be used for chaining commands (though it is not so good for assigning a variable.
hostname |for /f "tokens=* delims=" %%# in ('more') do #(ping %%#)
Which also can be beautified with macros:
#echo off
:: --- defining chain command macros ---
set "result-as-[arg]:=|for /f "tokens=* delims=" %%# in ('more') do #("
set "[arg]= %%#)"
::: -------------------------- :::
::Example:
hostname %result-as-[arg]:% ping %[arg]%
And for completnes macros for the temp file approach (no doskey definition ,but it also can be easy done.If you have a SSD this wont be so slow):
#echo off
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
set "[[=>"#" 2>&1&set/p "&set "]]==<# & del /q # >nul 2>&1"
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
chcp %[[%code-page%]]%
echo ~~%code-page%~~
whoami %[[%its-me%]]%
echo ##%its-me%##
For /f with another macro:
::::::::::::::::::::::::::::::::::::::::::::::::::
;;set "{{=for /f "tokens=* delims=" %%# in ('" &::
;;set "--=') do #set "" &::
;;set "}}==%%#"" &::
::::::::::::::::::::::::::::::::::::::::::::::::::
:: --examples
::assigning ver output to %win-ver% variable
%{{% ver %--%win-ver%}}%
echo 3: %win-ver%
::assigning hostname output to %my-host% variable
%{{% hostname %--%my-host%}}%
echo 4: %my-host%
cd %windir%\system32\inetsrv
#echo off
for /F "tokens=* USEBACKQ" %%x in (
`appcmd list apppool /text:name`
) do (
echo|set /p= "%%x - " /text:name & appcmd.exe list apppool "%%x" /text:processModel.identityType
)
echo %date% & echo %time%
pause
I most cases, creating a temporary file named after your variable name might be acceptable. (as you are probably using meaningful variables name...)
Here, my variable name is SSH_PAGEANT_AUTH_SOCK
dir /w "\\.\pipe\\"|find "pageant" > %temp%\SSH_PAGEANT_AUTH_SOCK && set /P SSH_PAGEANT_AUTH_SOCK=<%temp%\SSH_PAGEANT_AUTH_SOCK

Resources