I have a Windows 8 batch file where I'm trying to parse the output of a command to set a variable. The following works fine if the path inset frob=c:\path_to_frob\frob.exe contains no spaces:
for /f "tokens=5" %%i in ('%frob% -l ^| findstr "flux capacitor at "') do (
if NOT ERRORLEVEL 1 (
set flux_level=%%i
set /A flux_level=!flux_level:4,1!
)
)
But, if frob.exe is located at set frob=c:\path to frob\frob.exe then I get the error:
'c:\path' is not recognized as an internal or external command, operable program or batch file.
I've tried modifying the for loop with usebackq, but I get the same error:
for /f "usebackq tokens=4" %%i in ('"%frob%" -l ^| findstr "flux capacitor at "') do (
How do I get for /f to parse the output of a command with a complex path?
EDIT 1
This command:
for /F "tokens=4" %%i in ('"%frob%" -l ^| findstr /C:"flux capacitor at "') do (
expands to this:
for /F "tokens=4" %i in ('"c:\path to frob\frob.exe" -l | findstr /C:"flux capacitor at "') do (
'c:\path' is not recognized as an internal or external command,
operable program or batch file.
EDIT 2
I can verify the %frob% path is correct by putting:
"%frob%" --help
Just before the for /f loop. It works as expected and prints the application command-line help.
EDIT 3
If my findstr string is shorter and does not require quotes, then I don't get that error. For example, this command:
for /F "tokens=4" %%i in ('"%frob%" -l ^| findstr flux') do (
doesn't give me the error about frob's path.
for /f "tokens=4" %%i in ('"%frob%" -l ^| findstr /c:"flux capacitor at "') do (
set "flux_level=%%i"
set /A "flux_level=!flux_level:4,1!"
)
If %frob% contains spaces, quote it
a findstr command to search a string with spaces inside needs the search term indicated as /c:"..."
The commands executed in the in clause run in another cmd instance and the errorlevel is not accesible inside the do clause. If nothing is found, there will be no lines in the output of the pipe and the for will not execute the code in the do clause.
EDIT 1 - for command executes the command indicated in the in clause in a separate cmd instance. This instance retrieves, parses and executes the command. In some cases, the double quotes interfere, the initial and last quotes are removed (see cmd /? for more information) and the final command is wrong.
for /f "tokens=4" %%i in ('
" "%frob%" -l | findstr /c:"flux capacitor at " "
') do (
set "flux_level=%%i"
set /A "flux_level=!flux_level:4,1!"
)
Quote the full inner command in double quotes and remove the ^ in the pipe to handle the parse problem in the subshell
Remove the usebackq which changes the meanings of the different types of quotes.
The "quotes around the full program path and name" are required to escape the space-separators. the 'quotes round the command' are used to tell for /f that the string is a command to be executed. You'd probably get the same results using usebackq by using backticks (`) in place of single-quotes.
There's something mighty wrong here.
I've tried the following:
#ECHO OFF
SETLOCAL
SET "frob=u:\sourcedir\another dir\showparams.exe"
for /f "delims=" %%i in ('echo. ^|"%frob%" -l ') do (
ECHO %%i
)
ECHO ===============
SET "frob=u:\sourcedir\another dir\showparams.exe"
for /f "usebackq delims=" %%i in (`echo. ^|"%frob%" -l `) do (
ECHO %%i
)
ECHO ===============
FOR %%w IN ("%frob%") DO (
for /f "delims=" %%i in ('echo. ^|%%~dpnxsw -l ') do (
ECHO %%i
)
)
GOTO :EOF
Three different ways of executing a program located in a path containing spaces.
All worked perfectly - provided the file nominated as fob existed. Strangely, I received the same response as OP if the executable was missing :O
Obviously I don't have the OP's executable, but the method worked quite happily for me. I suspect an error in the value of frob.
Related
I'm trying to run a batch file with this code:
SET /a rotateval = 0
FOR /F "tokens=1,2" %%A IN ('C:\Users\Max\Google Drive\Misc\MaxPDFcompress\ImageMagick-7.0.9-7-portable-Q16-x64\convert "%%f" -format "%%[w] %%[h]" info:') DO (
IF %%A GTR %%B SET /a rotateval = 90
I'm getting the error that
'C:\Users\Max\Google' is not recognized as an internal or external command,
operable program or batch file.
I tried different combos of "delim=" and "usebackq" but to no avail.
The error you are reporting is double-quoting related in the parenthesized command within your FOR /F loop.
Your submitted content should look like this:
Set "rotateval=0"
For /F "Tokens=1,2" %%A In ('^""C:\Users\Max\Google Drive\Misc\MaxPDFcompress\ImageMagick-7.0.9-7-portable-Q16-x64\convert.exe" "%%f" -format "%%[w] %%[h]" info:^"') Do (
If %%A Gtr %%B Set "rotateval=90"
The parenthesized command is passed to another cmd.exe instance, and in doing so, it removes leading and closing double-quotes. To prevent that just place the entire command within escaped doublequotes, which when removed will leave your command as needed:
"C:\Users\Max\Google Drive\Misc\MaxPDFcompress\ImageMagick-7.0.9-7-portable-Q16-x64\convert.exe" "%f" -format "%[w] %[h]" info:
I have 10 text files in a folder and a jar file which will take three inputs one by one.
Text file path
Vendor Name
Model
I want to execute the Jar file 10 times (num of text files). I have a code that will execute 10 times and feed the first input "text file path"
#echo off
for %%a in (*.txt) do (
echo %%a|java -jar C:\Generator.jar
)
pause
I want to give the remaining two "Vendor name and Model" as console inputs one by one automatically. The vendor name and model should be populated by splitting text file name using underscore. Is there a way to achieve this ?
You can use for /f to split the file name into two tokens at the _ delimiter. You don't want to include the .txt extension, so you need to split %%~nA instead of %%A.
You could use dir with findstr to verify that the file name has valid format, and change the outer for loop to for /f to process that result. For example, you don't want to process a file name that looks like "vendor_.txt". My findstr command verifies there is only one _ and there is at least one non-underscore character both before and after.
One would think that the following would work
#echo off
:: This does not work - each line of input to java has an unwanted trailing space
for /f "delims=" %%A in (
'dir /a-d /b *_*.txt ^| findstr /i "^[^_][^_]*_[^_][^_]*\.txt$"'
) do for /f "delims=_ tokens=1*" %%B in ("%%~nA") do (
echo %%A
echo %%B
echo %%C
) | java -jar c:\generator.jar
But there is an insidious problem due to the fact that each side of the pipe is executed in a new cmd.exe process. Each side of the pipe must be parsed and packaged up into a cmd /c .... command. The left side ends up looking something like:
C:\Windows\system32\cmd.exe /S /D /C"echo fileName &echo vendor &echo model ",
with an unwanted space at the end of each line. Adding parentheses like (echo %%A) does not help.
There is another potential problem if any of the file names contain a poison character like &. If your vendor name is "Bell&Howell", then the left side process would attempt to execute
echo Bell&Howell. The "Bell" would echo properly, but the "Howell" would be interpreted as a command and would almost surely fail with an error, but in any case would not give the desired result.
See Why does delayed expansion fail when inside a piped block of code? for more information about potential issues with pipes, along with strategies for dealing with them.
Below is an enhancement to my original code that should fix the problems. I solve the poison character issue by putting the string literals within quotes, and then use a for statement that executes within the child cmd.exe process to safely strip the quotes before ECHOing the value.
I solve the unwanted trailing space issue by delaying parsing of the command by using an %%echoX%% "macro". The double percents delays expansion of the "macro" until after we are in the child process.
#echo off
setlocal disableDelayedExpansion
:: This echoX "macro" delays parsing of the echo command to avoid the unwanted trailing space
set "echoX=(echo %%~X)"
for /f "delims=" %%A in (
'dir /a-d /b *_*.txt ^| findstr /i "^[^_][^_]*_[^_][^_]*\.txt$"'
) do for /f "delims=_" tokens=1*" %%B in ("%%~nA") do (
(for %%X in ("%%~A" "%%B" "%%C") do #%%echoX%%) | java -jar c:\generator.jar
)
Another option is to define a multi-line variable with embedded linefeeds, and then use CMD /V:ON to enable delayed expansion in the child process.
#echo off
setlocal disableDelayedExpansion
for %%L in (^"^
%= This creates a quoted linefeed character in the FOR variable L =%
^") do for /f "delims=" %%A in (
'dir /a-d /b *_*.txt ^| findstr /i "^[^_][^_]*_[^_][^_]*\.txt$"'
) do for /f "delims=_" tokens=1*" %%B in ("%%~nA") do (
set "str=%%A%%~L%%B%%~L%%C"
cmd /v:on /c "(echo !str!)" | java -jar c:\generator.jar
)
Here is a simpler alternative that uses a temporary file instead of a pipe. It avoids the many issues that can arise with pipes.
#echo off
for /f "delims=" %%A in (
'dir /a-d /b *_*.txt ^| findstr /i "^[^_][^_]*_[^_][^_]*\.txt$"'
) do for /f "delims=_" tokens=1*" %%B in ("%%~nA") do (
>temp.txt (
(echo %%~A)
(echo %%B)
(echo %%C)
)
<temp.txt java -jar c:\generator.jar
del temp.txt
)
I have a batch file which runs a python script. The python script after completion sends a number like shown below:
I need my batch file to read its own output as it runs and then use this (the number 3 shown in figure below to do some processing
Is this possible with batch?
EDITED FOR CLARITY:
I want to have a script which uses "net use" command.
The output from this specific command is as shown below... which will be printed to cmd window in which script is running ! Now I want my script to read this output ..like if a certain address is found in the already mapped drives list it will do something..like unmap the drive
I don't understand quite well what your purpose is, what has to do python to do with capture the net use command output?
As a rule of thumb, to capture any command output, you must use a for loop (i.e. here capturing clipboard content using powershell
rem get clipboard content into variable
set "psCmd=powershell -Command "add-type -an system.windows.forms; [System.Windows.Forms.Clipboard]::GetText()""
for /F "usebackq delims=" %%# in (`%psCmd%`) do set "clipContent=%%#"
So, in order to grab the output of net use
#echo off
for /f "skip=6 tokens=2,3" %%a in ('net use') do (
echo/%%a | find ":">NUL && echo/Drive letter %%a - Remote name %%b
)
exit/B
But, I suggest that you better use wmic (following two are similar)
#echo off
for /f "useback skip=1 tokens=1,2" %%a in (`"wmic path Win32_LogicalDisk Where DriveType="4" get DeviceID, ProviderName"`) do (
echo/%%a | find ":">NUL && echo/Drive letter %%a - Remote name %%b
)
exit/B
or
#echo off
for /f "useback skip=1 tokens=1,2" %%a in (`"wmic path Win32_MappedLogicalDisk get DeviceID, ProviderName"`) do (
echo/%%a | find ":">NUL && echo/Drive letter %%a - Remote name %%b
)
exit/B
Since, you may add the /node:"some_other_computer_name" switch to wmic and may list mapped drives from any computer on the net, i.e
#echo off
for /f "useback skip=1 tokens=1,2" %%a in (`"wmic /node:"hp-ml110" path Win32_MappedLogicalDisk Where DriveType="4" get DeviceID, ProviderName"`) do (
echo/%%a | find ":">NUL && echo/Drive letter %%a - Remote name %%b
)
exit/B
Hope it helps.
I am still pretty new to batch and im running into this issue that i cannot seem to solve. When I run my script it returns "6766.txt" was unexpected at this time.My script is supposed to search for "store_versions" in a file called Local State. If it finds that line it it will be appended to a Temp file and then trim the line in a loop so that i only get A specific part of the output of the find command. The output of the command is [319] "store_versions": { . And all I want is 319. Does anyone know what is causing this issue?
Thanks,
#echo off
setlocal enableextensions enabledelayedexpansion
set tempfile="%random%.txt"
set LineNumFin=%LineNumFin%
pause
Find /N "store_versions" < "Local State" > %tempfile%
for /f "tokens=1 delims=[]" %%a in %tempfile% do ( set LineNum=%%a
pause
)
del "%tempfile%"
echo Line Num: %LineNum%
set /a result=%LineNum%+4
echo %result%
The in clause of the for command needs parenthesis
for /f "... options ..." %%a in ( file ) do ....
^ ^
^ here ^
And, as you are including quotes in the name of the file, you will need to include usebackq in the options part of the for command
Or, you can avoid the temporary file
for /f "tokens=1 delims=[]" %%a in (
' find /n "store_versions" ^< "Local State" '
) do set "lineNum=%%a"
The for command will execute the command, tokenize the records and retrieve the value.
Could you please advise how to fix command below, which removes unversioned items from svn
rem #echo off
for /f "tokens=2*" %%i in ('"c:\Program Files\TortoiseSVN\bin\svn.exe" status --no-ignore ^| find "?"') do echo %%i
variant below without path works:
rem #echo off
for /f "tokens=2*" %%i in ('svn.exe status --no-ignore ^| find "?"') do echo %%i
but i need to pass entire path with svn.exe. In this case it outputs C:\Program is not a valid program
try with this:
for /f "usebackq tokens=2*" %%i in (`"c:\Program Files\TortoiseSVN\bin\svn.exe" status --no-ignore ^| find "?"`) do echo %%i
When I ran into this problem, I tried using "usebackq" as suggested in the Windows command reference[1]:
Specifies to execute a back-quoted string as a command, and a single-quoted string as a literal string command. Also, allows file names in Set to be enclosed in quotation marks.
I found that this still gave an error about C:\Program not being executable.
Then I remembered, that Windows cmd.exe has really weird quoting rules, where if the first and last character in an executed string are quotes, they will be stripped[2].
So I tried this, and it worked for me:
for /F usebackq %%d in (`""path to command" arg arg "quoted arg""`) do #echo %%d
[1] http://technet.microsoft.com/en-us/library/cc754900.aspx
[2] http://technet.microsoft.com/en-us/library/cc771320.aspx
Going off of Ben's answer above (https://stackoverflow.com/a/25084830/2630028), the below example worked for me:
for /f "usebackq delims=" %%j in (`^""C:\Perl64\bin\perl" -e "print(qq(foo))"^"`) do (
echo LINE: %%j
)
It seems like I have to escape the outer quotes with ^ (https://ss64.com/nt/syntax-esc.html).