This is the problem I'm having:
#ECHO OFF
REM If this batch file is run in the same directory as "command.exe" then the
REM following line will work.
FOR /F "usebackq" %%A IN (`command.exe "C:\File Being Passed as a Parameter.txt"`) DO ECHO %%A
REM The following line does not work no matter where this batch file is run.
FOR /F "usebackq" %%A IN (`"C:\Folder With Spaces\command.exe" "C:\File Being Passed as a Parameter.txt"`) DO ECHO %%A
I would like to store this batch file wherever I want and not be forced to store it in the same folder as command.exe. Any suggestions?
Add CALL before the program name:
FOR /F "usebackq" %%A IN (`CALL "C:\Folder With Spaces\command.exe" "C:\File Being Passed as a Parameter.txt"`) DO ECHO %%A
The call trick of Andriy M is clever and works fine, but I tried to understand the problem here.
This problem is caused by the cmd.exe, as you can read at cmd /help
....
the first and the last quote will be removed, when there are
not exactly two quotes in the line.
...
So there is also another solution with simply adding two extra quotes
FOR /F "usebackq=" %%A IN (`""C:\Folder Space\myCmd.exe" "Param space""`) DO (
ECHO %%A
)
Careful:
Using 'call' (as shown by Andriy M) seems the safest option.
I found a case where adding leading and trailing double quotes (as suggested as a possible solution by jeb) has a problem.
Problem:
for /f "delims=" %%i in ('""C:\path with spaces\hello.bat" "filename with an & ampersand.jpg""') do ( echo output=%%i )
cmd.exe's output: & was unexpected at this time.
Solution:
for /f "delims=" %%i in ('call "C:\path with spaces\hello.bat" "filename with an & ampersand.jpg"') do ( echo output=%%i )
Related
I'm working on a DOS script in order to search a line and replace it into files from a specific folder. Here is what i have already done :
#echo off
setlocal enableextensions disabledelayedexpansion
set "search=#Interceptors({ RuntimeExceptionInterceptor.class }^)"
set "replace=#Interceptors({ RuntimeExceptionInterceptor.class, ReportInterceptor.class, CorrelationIdInterceptor }^)"
set "textFile=C:\Utilisateurs\a669884\Documents\test.txt"
for %%a in (*.txt) do (
echo "%%a"
for /f "Delims=" %%i in (%%a ^& break ^> %%a) do (
set "line=%%i "
setlocal enabledelayedexpansion
>>%%a echo(!line:%search%=%replace%!
endlocal
)
)
Problem is that my first line is not replace by the new one, the new line is added under it like that :
#Interceptors({ RuntimeExceptionInterceptor.class })
#Interceptors({ RuntimeExceptionInterceptor.class, ReportInterceptor.class, CorrelationIdInterceptor })
Do you know why my first line isn't replaced? Thanks a lot
Seb
Not sure what setting textfile has to do with the routine - it's not used.
Your original code produced a complaint that & was not found and created an empty file for me.
Changing the for to
for /f "Delims=" %%i in ('type "%%a" ^& break ^> "%%a"') do (
seemed to make the substitution, given the one line (partial?) of sourcefile you've provided, plus a few dummy lines.
execute the type... with the filenames enclosed in quotes to ensure correct operation with separators, replacing the file; substitute as specified.
I have a batch script that would concatenate the content of files that were listed in an index file. It used to work until there were spaces in the paths. I have edited it a bit, but it is something like this:
SET INPUT="C:\Has Spaces In Path\indexfile.txt"
SET ROOT="C:\Has Spaces In Path\inputdirectory\"
SET OUTPUT="C:\Has Spaces In Path\outputdirectory\mergedfile.txt"
FOR /F %%A IN (%INPUT%) DO TYPE "%ROOT%%%A" >> "%OUTPUT%"
The problem I have is that %INPUT% now appears to get tokenised in the for loop and if I put quotes around it (i.e. "%INPUT%") it does not work either. Is there any way I can get this loop to iterate over each line in the file specified by INPUT and concatenate the contents to the OUTPUT file?
Thanks.
Edit: Based on the answer, this did what I wanted:
FOR /F %%A IN ('type "%INPUT%"') DO TYPE "%ROOT%%%A" >> "%MERGED%"
FOR /F %%A IN ('type %INPUT%') DO echo %%A
' in the brackets will cause to execute the statement and uses the output like a file source
FOR /F "usebackq" %%A IN ("%INPUT%") DO TYPE "%ROOT%%%A" >> "%OUTPUT%"
or, better yet:
(FOR /F "usebackq" %%A IN ("%INPUT%") DO TYPE "%ROOT%%%A") > "%OUTPUT%"
For further details, see: FOR /?
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).
I'm trying to work up a batch file to combine two pieces of text on one line. The first is the filename; the second is the first line of text beginning with "To: ". I have been struggling for hours and this is as far as I've gotten:
#echo off
IF EXIST fullnames.txt DEL fullnames.txt
FOR /F %%g IN ('dir /b *.eml') DO (
SET filename=%~f1
SET toline=FINDSTR /B /C "To: "
ECHO %FILENAME%%TOLINE% >> fullnames.txt
)
and it doesn't work. I am getting errors or incorrect results almost regardless of what I put down for the filename line; haven't even begun to test the toline part. Any suggestions?
You already used FOR /F to capture the output of the DIR command. Capturing the output of FINDSTR is no different.
However, it is more efficient to use a simple FOR in place of the FOR /F with the DIR command.
You used %~f1 when I think you intended %%~fg.
You cannot expand a variable set within parentheses using %var%, you must use !var! delayed expansion instead. Type SET /? from the command line for more information - read the section starting with "Finally, support for delayed environment variable expansion has been
added..."
However, in your case, you can easily avoid using delayed expansion (not that it is a problem).
Instead of deleting any existing "fullnames.txt" and then appending output to it, it is more efficient to enclose the entire construct within parentheses and redirect all output to the file using the over-write mode.
#echo off
(
for %%F in (*.eml) do (
for "delims=" %%A in ('findstr /b /c:"To: " "%%F"') do echo %%F %%A
)
) >fullnames.txt
But the above solution, simple as it is, is much more complicated than it needs to be.
FINDSTR can process multiple files specified with wildcards, and it will prefix each matching line with the filename followed by a colon.
You can get your results simply from the command line without even using a batch file (or you could put this in a batch file):
findstr /b /c:"To: " *.eml >fullnames.txt
Edit
If you are concerned that a file might contain multiple lines starting with "To: ", and you only want to use the first line, then it is back to using a batch file:
#echo off
setlocal enableDelayedExpansion
set "prevFile="
(
for /f "tokens=1* delims=:" %%A in ('findstr /b /c:"To: " *.eml') do (
if "%%A" neq "!prevFile!" echo %%A: %%B
set "prevFile=%%A"
)
) >fullnames.txt
The above solution could fail if a filename contains !. Also, a path could be used with *.eml as long as the path does not contain a drive letter. Both the drive and ! issues can be resolved with additional modifications.
#echo off
setlocal EnableDelayedExpansion
if exist fullnames.txt del fullnames.txt
for %%f in (*.eml) do (
set toline=
for /F "delims=" %%l in ('findstr /B /C:"To: " "%%f"') do (
if not defined toline set "toline=%%l"
)
echo %%f!toline! >> fullnames.txt
)
EDIT: Simpler method added
The set toline= command delete 'toline' variable before each file is processed, so just the first "To: " matching line found is assigned to it and later shown using Delayed Expansion. However, this process may be achieved in a simpler way that doesn't require Delayed Expansion, as dbenham suggested:
#echo off
if exist fullnames.txt del fullnames.txt
for %%f in (*.eml) do (
set firstFind=
for /F "delims=" %%l in ('findstr /B /C:"To: " "%%f"') do (
if not defined firstFind set firstFind=now & echo %%f%%l >> fullnames.txt
)
)
You can't assign and use environment variables inside a for loop. Use delayed variable expansion or call a subroutine.
Delayed would look something like this
setlocal EnableDelayedExpansion
#echo off
IF EXIST fullnames.txt DEL fullnames.txt
FOR /F %%g IN ('dir /b *.eml') DO (
SET filename=%~f1
SET toline=FINDSTR /B /C "To: "
ECHO !FILENAME!!TOLINE! >> fullnames.txt
)
However, that doesn't look like it would work correctly anyway. I would do it like this
FOR /F %%g IN ('dir /b *.eml') DO call :process %%g
goto :eof
:process
SET filename=%~f1
SET toline=FINDSTR /B /C "To: "
ECHO %FILENAME%%TOLINE% >> fullnames.txt
I have a log file which I need to read in, line by line and pipe the line to a next loop.
Firstly I grep the logfile for the "main" word (like "error") in a separate file - to keep it small. Now I need to take the seperate file and read it in line by line - each line needs to go to another loop (in these loop I grep the logs and divide it in blocks) but I stuck here.
The log looks like
xx.xx.xx.xx - - "http://www.blub.com/something/id=?searchword-yes-no" 200 - "something_else"
with a for /f loop I just get the IP instead of the complete line.
How can I pipe/write/buffer the whole line? (doesn't matter what is written per line)
Try this:
#echo off
for /f "tokens=*" %%a in (input.txt) do (
echo line=%%a
)
pause
because of the tokens=* everything is captured into %a
edit:
to reply to your comment, you would have to do that this way:
#echo off
for /f "tokens=*" %%a in (input.txt) do call :processline %%a
pause
goto :eof
:processline
echo line=%*
goto :eof
:eof
Because of the spaces, you can't use %1, because that would only contain the part until the first space. And because the line contains quotes, you can also not use :processline "%%a" in combination with %~1. So you need to use %* which gets %1 %2 %3 ..., so the whole line.
The "call" solution has some problems.
It fails with many different contents, as the parameters of a CALL are parsed twice by the parser.
These lines will produce more or less strange problems
one
two%222
three & 333
four=444
five"555"555"
six"&666
seven!777^!
the next line is empty
the end
Therefore you shouldn't use the value of %%a with a call, better move it to a variable and then call a function with only the name of the variable.
#echo off
SETLOCAL DisableDelayedExpansion
FOR /F "usebackq delims=" %%a in (`"findstr /n ^^ t.txt"`) do (
set "myVar=%%a"
call :processLine myVar
)
goto :eof
:processLine
SETLOCAL EnableDelayedExpansion
set "line=!%1!"
set "line=!line:*:=!"
echo(!line!
ENDLOCAL
goto :eof
This has worked for me in the past and it will even expand environment variables in the file if it can.
for /F "delims=" %%a in (LogName.txt) do (
echo %%a>>MyDestination.txt
)
For those with spaces in the path, you are going to want something like this:
n.b. It expands out to an absolute path, rather than relative, so if your running directory path has spaces in, these count too.
set SOURCE=path\with spaces\to\my.log
FOR /F "usebackq delims=" %%A IN ("%SOURCE%") DO (
ECHO %%A
)
To explain:
(path\with spaces\to\my.log)
Will not parse, because spaces.
If it becomes:
("path\with spaces\to\my.log")
It will be handled as a string rather than a file path.
"usebackq delims="
See docs will allow the path to be used as a path (thanks to Stephan).