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 /?
Related
I have been searching through StackOverflow but could not find an answer that hits the mark. I have 2 .txt files to compare and return a 3rd one where differences exist.
However, only the first column of the first 2 files need a comparison.
E:\Compare_flie\file_1.txt
GND ZERO
22XC44 XXYYZZ
33XC55 YYUUTT
E:\Compare_file\file_2.txt
GND ZERO
22XC44 KK77UU
33XC55 88JJ66
66NN77 HHOO99
99CC88 UU77RR
E:\Compare_file\file_3.txt (intended output)
66NN77 HH0099
99CC88 UU77RR
Tried the code below but it is only good at picking out the differences of all the strings in the line
%echo on
findstr /v /i /g:E:\Compare_files\file_1.txt E:\Compare_files\file_2.txt
> E:\Compare_files\file_3.txt
Refined it further but not hitting the mark yet.
%echo on
for /f "tokens=1 delims= " %%I in ("E:\Compare_files\file_1.txt") do
findstr /v /i "%%I"/g:"D:\Compare_files\file_2.txt"
> "D:\Compare_files\file_3.txt"
Appreciate if anyone can assist.
#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
SET "destdir=U:\destdir"
SET "filename1=%sourcedir%\q48816766.txt"
SET "filename2=%sourcedir%\q48816766_2.txt"
SET "tempfile=%temp%\q48816766.tmp"
SET "outfile=%destdir%\outfile.txt"
(FOR /f "usebackq" %%a IN ("%filename1%") DO ECHO %%a )>"%tempfile%"
FINDSTR /b /v /g:"%tempfile%" "%filename2%">"%outfile%"
REM DEL "%tempfile%" /F /Q
GOTO :EOF
I've set up names to suit my system, but with the two files containing your data.
Obviously, the usebackq on the for/f is only required if the filename is quoted. The parentheses around the command permit the echoed output to be accumulated into the temporary file. What's important here is the space between the %%a and ). This ensures that the temporary file contains trailing spaces.
Then apply the temporary file to the second data file via /g as in OP's code. The presence of the trailing spaces in the tempfile ensure that the only lines selected for omission are those where the first column exactly matches so for instance had 66NN7 appeared in the first file, first column, then this would not match 66NN77 in the second file.
Here's a method using batch with the type command piping the first file's contents over to the findstr command then passing the arguments accordingly to redirect those results into a temp file.
Using a for /f loop with "usebackq tokens=1 delims= " it will iterate through the temp file and for each line in that file parsing accordingly, it will append the column one lines with an echo command using >> to redirect the results over to file_3.txt with the expected results.
Please note the addition of the if exist "%srcdir%\file_3.txt" del /q /f "%srcdir%\file_3.txt" to delete that file if it exists since the for /f echo commands will append one after the other to it.
#echo on
set srcdir=E:\Compare_files
set tmpfile=%temp%\%~N0.tmp
type "%srcdir%\file_1.txt" | findstr /vig:"%srcdir%\file_2.txt">"%tmpfile%"
if exist "%srcdir%\file_3.txt" del /q /f "%srcdir%\file_3.txt"
for /f "usebackq tokens=1 delims= " %%I in ("%tmpfile%") do (
echo %%~I>>"%srcdir%\file_3.txt"
)
Further Resources
FOR /F
FOR /?
usebackq - specifies that the new semantics are in force,
where a back quoted string is executed as a
command and a single quoted string is a
literal string command and allows the use of
double quotes to quote file names in
file-set.
Redirection
Comparing/finding the difference between two text files using findstr
As I understand your problem, you want the lines from file_2.txt whose first column are not contained in first column of file_1.txt, that is: file_2.txt minus file_1.txt. There is a simpler approach to get such result:
#echo off
setlocal
rem Fill "line" array with lines from file_2.txt
rem use the first column for the array keys
for /F "delims=" %%a in (file_2.txt) do for /F %%b in ("%%a") do set "line[%%b]=%%a"
rem Delete array elements with same key from file_1.txt
for /F %%b in (file_1.txt) do set "line[%%b]="
rem Show remaining elements
(for /F "tokens=1* delims==" %%a in ('set line[') do echo %%b) > file_3.txt
I need a batch script that will read in another batch script (batch2) and:
look for the string "configout:" OR "configin:"
If it encounters one of these two strings, extract what's after it until the string ".xml"
copy paste it in a new text file.
and do this for each line of batch2.
For exemple:
If this is my first line in the batch script
/configin:%faxml%fm_sellin_in.xml /configout:%faxml%transco_fm_sellin_out%col_transco%.xml /inputfile:
I should have this in my text file:
%faxml%fa_sellin_in.xml
%faxml%transco_fm_sellin_out%col_transco%.xml
I have seen a good code in Here:
for /f "tokens=1-2 delims=~" %%b in ("yourfile.txt") do (
echo %%b >> newfile.txt
echo removed %%a)
but i don't know how to adapt it to my specific case.
Why not replace all the /configin and /configout with newlines? -
(Replace string with a new line in Batch)
For example
setlocal EnableDelayedExpansion
set "str=/configin:%%faxml%%fm_sellin_in.xml /configout:%%faxml%%transco_fm_sellin_out%%col_transco%%.xml /inputfile:"
set str=!str:/configin^:=^
!
set str=!str:/configout^:=^
!
Now, !str! would contain
fm_sellin_in.xml
transco_fm_sellin_out.xml /inputfile:
Then, you could use the for loop to extract the strings
for /f "tokens=1,2 delims=. " %%a in ("!str!") do ()
this for loop iterates through each line and splits each line with the and . characters.
So %%a is your file name and %%b is the extension.
then
if [%%b]==[xml] (echo %%a.%%b>>mytextfile.txt)
We will do this for all the lines of batch2.
And the finished code is
setlocal EnableDelayedExpansion
for /f "delims=" %%c in (batch2.txt) do (
set str=%%c
set str=!str:/configin^:=^
!
set str=!str:/configout^:=^
!
for /f "tokens=1,2 delims=. " %%a in ("!str!") do (if [%%b]==[xml] (echo %%a.%%b>>mytextfile.txt))
)
ok I am trying to strip the first two characters from a file I am using this script.
#echo off
Set "InputFile=C:\New Folder\test.txt"
Set "OutputFile=C:\New Folder\New\test.txt"
setLocal EnableDelayedExpansion > "%OutputFile%"
for /f "usebackq tokens=* delims= " %%a in ("%InputFile%") do (
set s=%%a
>> "%OutputFile%" echo.!s:~2!
)
which works perfect if I use the correct name. What I need to do is use a wild characters since the name of the file is different each time. When trying this it does not work.
#echo off
Set "InputFile=C:\New Folder\H*.txt"
Set "OutputFile=C:\New Folder\New\H*.txt"
setLocal EnableDelayedExpansion > "%OutputFile%"
for /f "usebackq tokens=* delims= " %%a in ("%InputFile%") do (
set s=%%a
>> "%OutputFile%" echo.!s:~2!
)
from
I'd like to use a wildcard with the SET command in Windows Batch so I don't have to know exactly what is in the string in order to match it
The asterisk IS a wildcard and WILL match multiple characters, but
will ONLY match everything from the very beginning of the string. Not
in the middle, and not from the end.
Useful Searches:
*x
*how are you? The above two searches CAN be matched. The first will match everything up to and including the first "x " it runs across.
The second one will match everything up to and including the first
"how are you?" it finds.
Legal, but Unuseful, searches:
x* Hello* OneThree The above three searches can NEVER be matched.
Oddly they are also legal, and will cause no errors. One exception:
Hello and x* WILL match themselves, but only if they are the very
beginning of the string. (Thanks Jeb!)
the surrounding for-loop does the wildcard processing (giving full qualified filenames)
#echo off
for /f %%i in ('dir /b C:\New Folder\H*.*') do (
echo processing %%i
Set "InputFile=C:\New Folder\%%i"
Set "OutputFile=C:\New Folder\New\%%i"
setLocal EnableDelayedExpansion > "%OutputFile%"
for /f "usebackq tokens=* delims= " %%a in ("%InputFile%") do (
set s=%%a
>> "%OutputFile%" echo.!s:~2!
)
endlocal
)
Note: if you have more than one line in those files, it will remove the first two characters from each line*.
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 )
How you can read a file (text or binary) from a batch file? There is a way to read it in a binary mode or text mode?
Under NT-style cmd.exe, you can loop through the lines of a text file with
FOR /F %%i IN (file.txt) DO #echo %%i
Type "help for" on the command prompt for more information. (don't know if that works in whatever "DOS" you are using)
The FOR-LOOP generally works, but there are some issues.
The FOR doesn't accept empty lines and lines with more than ~8190 are problematic.
The expansion works only reliable, if the delayed expansion is disabled.
Detection of CR/LF versus single LF seems also a little bit complicated.
Also NUL characters are problematic, as a FOR-Loop immediatly cancels the reading.
Direct binary reading seems therefore nearly impossible.
The problem with empty lines can be solved with a trick. Prefix each line with a line number, using the findstr command, and after reading, remove the prefix.
#echo off
SETLOCAL DisableDelayedExpansion
FOR /F "usebackq delims=" %%a in (`"findstr /n ^^ t.txt"`) do (
set "var=%%a"
SETLOCAL EnableDelayedExpansion
set "var=!var:*:=!"
echo(!var!
ENDLOCAL
)
Toggling between enable and disabled delayed expansion is neccessary for the safe working with strings, like ! or ^^^xy!z.
That's because the line set "var=%%a" is only safe with DisabledDelayedExpansion, else exclamation marks are removed and the carets are used as (secondary) escape characters and they are removed too.
But using the variable var is only safe with EnabledDelayedExpansion, as even a call %%var%% will fail with content like "&"&.
EDIT: Added set/p variant
There is a second way of reading a file with set /p, the only disadvantages are that it is limited to ~1024 characters per line and it removes control characters at the line end.
But the advantage is, you didn't need the delayed toggling and it's easier to store values in variables
#echo off
setlocal EnableDelayedExpansion
set "file=%~1"
for /f "delims=" %%n in ('find /c /v "" %file%') do set "len=%%n"
set "len=!len:*: =!"
<%file% (
for /l %%l in (1 1 !len!) do (
set "line="
set /p "line="
echo(!line!
)
)
For reading it "binary" into a hex-representation
You could look at SO: converting a binary file to HEX representation using batch file
You can use the for command:
FOR /F "eol=; tokens=2,3* delims=, " %i in (myfile.txt) do #echo %i %j %k
Type
for /?
at the command prompt. Also, you can parse ini files!
One very easy way to do it is use the following command:
set /p mytextfile=< %pathtotextfile%\textfile.txt
echo %mytextfile%
This will only display the first line of text in a text file. The other way you can do it is use the following command:
type %pathtotextfile%\textfile.txt
This will put all the data in the text file on the screen. Hope this helps!
settings.ini
name="John"
lastName="Doe"
script.bat
#echo off
for /f "tokens=1,2 delims==" %%a in (settings.ini) do (
if %%a==name set %%a=%%b
if %%a==lastName set %%a=%%b
)
echo %name% %lastName%
Well theres a lot of different ways but if you only want to DISPLAY the text and not STORE it anywhere then you just use: findstr /v "randomtextthatnoonewilluse" filename.txt
Corrected code :
setlocal enabledelayedexpansion
for /f "usebackq eol= tokens=* delims= " %%a in (`findstr /n ^^^^ "name with spaces.txt"`) do (
set line=%%a
set "line=!line:*:=!"
echo(!line!
)
endlocal
pause