Capturing variables from a CSV file determined by numeric range in a Windows Batch File - batch-file

I have the following data in a # delimited CSV data file called clean.txt:
1 LINK#FSN News Cart#<< DO NOT DELETE or MOVE >>#0#27000
2 LINK#News Outro#<< DO NOT DELETE or MOVE >>#27000#33000
3 SONG#Blow My Mind (feat. Chris Brown)#Davido#33000#199000
4 SONG#So Good#Alex Blue#199000#361000
5 SONG#Easy To Love (feat. Teddy Swims)#Armin van Buuren and Matoma#367000#517000
6 SONG#Anti-Hero (Roosevelt Remix)#Taylor Swift#517000#725000
7 SONG#Simmer (feat. Burna Boy) (Majestic Remix)#Mahalia#730000#929000
8 SONG#Pyramid (Michael Calfan Remix)#John Dahlback#929000#1121000
9 SONG#I Told You Once#Si Sax#1121000#1311000
10 SONG#I'm Every Woman#Whitney Houston and SG Lewis#1311000#1538000
11 SONG#Overnight#Tobtok and Adam Griffin#1544000#1698000
12 SONG#Hungry (For Love)#LF SYSTEM#1698000#1840000
13 LINK#Slogan#Theme A#1840000#1849000
14 SONG#If You Want Me To Stay (Eric Kupper Edit)#The Lovefreekz and Nick Reach Up#1849000#2029000
15 SONG#Never Too Late#Olivia Nelson#2029000#2220000
16 SONG#Celestial#Ed Sheeran#2224000#2427000
17 SONG#Out Of My Depth (feat. Nu-La)#CHANEY#2427000#2595000
18 SONG#All By Myself#Alok, Sigala and Ellie Goulding#2595000#2761000
19 SONG#Sweet Lies#Nathan Dawe and Talia Mar#2761000#2880000
20 SONG#Down In Atlanta#Pharrell Williams and Travis Scott#2882000#3038000
21 SONG#More Than Ever#Harry Shadow and Jodapac#3038000#3216000
22 SONG#What You Gonna Do (feat. Taet)#CLIK3D#3216000#3391000
23 SONG#Let It Go#Ryan Shepherd#3391000#3555000
24 SONG#2 Be Loved (Am I Ready) (PNAU Remix)#Lizzo#3555000#3773000
25 SONG#Perfect Love#Tom Westy and Mila Falls#3773000#3931000
26 LINK#ID#Theme A#3931000#3936000
27 LINK#Website Promo#HHUK#3936000#3974000
28 LINK#News Intro and Bed - WITH FADE#<< DO NOT DELETE or MOVE >>#3974000#3983000
The fields on each row are:
<ITEM>#<TITLE>#<ARTISTS>#<START>#<END>
START and END are integers in milliseconds.
The objective is to display the <TITLE> - <ARTIST> that corresponds to a time between <START> and <END> The time is provided in an input variable.
The following script works with a hard-coded input variable (Dur) of 1000000 or less, but if I go above that I get multiple results and I can’t figure out why.
set /a Dur=1000000
for /F "tokens=1-5 delims=#" %%i in (clean.txt) do (
If %Dur% GEQ %%l (if %Dur% LEQ %%m echo %%i %%l %%m TRACK %%k - %%j)
)
I have tried dividing all of the numbers in the data file by 1000 to reduce the size but that didn’t make any difference.

You can easily (and fast) solve this problem this way:
#echo off
setlocal EnableDelayedExpansion
set /a Dur=1000000
for /F "tokens=1-5 delims=#" %%i in (clean.txt) do (
set /A "inRange=((%%l-Dur)>>31)*((Dur-%%m)>>31)"
if !inRange! EQU 1 echo %%i %%l %%m TRACK %%k - %%j
)
The rationale of the used formula is explained with detail at this post. This is a summary:
set /A (lowerLimit-variable) is negative if variable > lowerLimit
set /A (variable-UpperLimit) is negative if variable < upperLimit, so
set /A (lowLimit-var)*(var-UpLimit) is positive if variable is in range
In this case the result of the subtractions is reduced to a -1 or 0 values with an >>31 arithmetic shift right of 31 bits in order to avoid any overflow when large values are multiplied.

Your comparisons are bein performed alphabetically; 1 as the first character in a string is always less than any other digit.
You need to force arithmetic comparison, or find a way around the string-comparison.
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
set /a Dur=1200000
for /F "tokens=1-5 delims=#" %%i in (q75313286.txt) do (
rem will set cond1 to +ve if first condition is true, -ve otherwise
SET /a cond1=%dur% - %%l
rem ditto second condition
SET /a cond2=%%m - %dur%
ECHO !cond1!!cond2! |FIND "-">NUL
rem if either is negative, errorlevel will be 0
IF ERRORLEVEL 1 echo %%i %%l %%m TRACK %%k - %%j
rem If %Dur% GEQ %%l (if %Dur% LEQ %%m echo %%i %%l %%m TRACK %%k - %%j)
)
GOTO :EOF
Always verify against a test directory before applying to real data.
I used a file named q75313286.txt containing your data for my testing.
---- Improved "for" loop
for /F "tokens=1-5 delims=#" %%i in (q75313286.txt) do (
rem will set cond1 to +ve if first condition is true, -ve otherwise
SET /a cond1=%dur% - %%l
rem ditto second condition
SET /a cond2=%%m - %dur%
SET "cond1=!cond1!!cond2!"
IF "!cond1!"=="!cond1:-=!" echo %%i %%l %%m TRACK %%k - %%j
rem If %Dur% GEQ %%l (if %Dur% LEQ %%m echo %%i %%l %%m TRACK %%k - %%j)
)
By concatenating the results of the two calculations, you get a string that may contain 0,1 or 2 - characters.
Instead of checking that string by way of echo...find..., see whether the string is the same as [the same string, with - replaced by nothing]. If it is, then there are no - characters in the string. This is a lot faster than the echo...find... method (albeit insignificant - it's the principle)

Related

Assign each line of the text file to a variable to verify numbers are in sequence in windows batch script

I'm learning windows batch-file script and creating my own scripts to practice the coding but kind of hit a block while try find whether the numbers in a text file is in sequence or not.I have two files,one file(file.txt) contains the number of lines in file_received.txt. The file_received.txt content is below:
1021
1022
1023
1024
1025
1027
1028
I'm building a script to test whether all the numbers in the text file are in sequence .so as a first step I'm trying to extract each line of the file_received to be assigned to a variable through if / for loop but the if command loop assigning all the lines to the variable num from file_received.txt at the same time. Is it possible to assign first line of the file to variable num and increment it as the if loops increment?
setlocal EnableDelayedExpansion
rem assign the number of lines to a variable
set /P var=<C:\files.txt
for /F "tokens=1" %%a in ("%var%") do echo.%%a
rem assign the first variable to var1
set /P var1=<C:\files_received_sequence.txt
for /F "tokens=1" %%a in ("%var1%") do echo.%%a
set /a x=1
:while
if %x% leq %var% (
echo %x%
rem assigning each line to the variable num inside the if loop and will be used in comparison and reser
for /F "tokens=%x%" %%i in (C:\files_received.txt) do set num=%%i
echo %num%
set /a x+=1
goto :while
)
echo test :D
the output is as below in loop 1 the entire file content is assigned to the variable num and from loop 2 to 7 the last number is assigned.
C:\>setlocal EnableDelayedExpansion
C:\>set /P var= 0<C:\files.txt
C:\>for /F "tokens=1" %a in ("7 ") do echo.%a
C:\>echo.7
7
C:\>set /P var1= 0<C:\files_received.txt
C:\>for /F "tokens=1" %a in ("1021") do echo.%a
C:\>echo.1021
1021
C:\>set /a x=1
C:\>if 1 LEQ 7 (
echo 1
for /F "tokens=1" %i in (C:\files_received.txt) do set num=%i
echo
set /a x+=1
goto :while
)
1
C:\>set num=1021
C:\>set num=1022
C:\>set num=1023
C:\>set num=1024
C:\>set num=1025
C:\>set num=1027
C:\>set num=1028
ECHO is on.
C:\>if 2 LEQ 7 (
echo 2
for /F "tokens=2" %i in (C:\files_received.txt) do set num=%i
echo 1028
set /a x+=1
goto :while
)
2
1028
Here's the logic I'd use to test that each number is in sequence incrementing by one (and only one) each time:
#Echo off & Setlocal EnableDelayedExpansion
Set "ln="
For /F "Delims=" %%i in (C:\file_received.txt) Do (
If Not "!ln!"=="" For /F "UseBackQ Delims=" %%v in (`"Set /A Nx=!ln!+1"`) Do (If Not "%%i"=="%%v" (Echo/OoS:!ln!/%%i & Goto :False))2> Nul
Set "ln=%%i"
)
Echo/True
Exit /B 0
:False
Echo/False
Exit /B 1
Here is a version that will highlight the item not in sequence. Do note, that it will test sequence only, in other words ensure the previous result is lower than the next
#echo off & setlocal enabledelayedexpansion
set rev=-1
for /f "delims=" %%a in (files_received.txt) do for %%i in (%%a) do (
if %%i leq !rev! (
echo %%i Out of sequence
) else (
echo %%i
set rev=%%i
)
)
besides you don't use delayed expansion (although you have enabled it), your logic is far too complicated:
#echo off
setlocal enabledelayedexpansion
set last=-1
for /f %%a in (t.txt) do (
if %%a lss !last! (
echo not in sequence
goto :eof
)
set "last=%%a"
)
echo all in sequence.
the variable !last! holds the value from the previous iteration of the loop.
(Depending on your needs, you may want to replace lss with leq)

SubString not working properly within a for loop in batch script

I am trying to read a text file "data.txt" which contains some data in the given format:
data = 12 39 43 45 05 32 77 34 87 93 72 21 04 23 03 12 06 11 15 32 12 14 05 15 17 15 29 33 15
first I need to extract only the data next to the string data = and then process this data in the following manner:
-Parse fifth element and multiply it with a constant 3 to sub-string the whole string by the result of the multiplication. For example: in the above data, fifth element is 5 so I need to sub-string 15 characters starting from 32 until 93, write them to text file and then override the current data with data after 93 and so on..
The code works fine without the for loop but when I need the loop to update the variables and process more than one iteration it keeps parsing same data every time.
Can you please advise ?
#echo off
SETLOCAL ENABLEEXTENSIONS EnableDelayedExpansion
REM Exclude "data=" from the text
for /F "tokens=2 delims==" %%B in ('findstr /I "data = " data.txt') do (
set "Current_data=%%B"
)
for /L %%s IN (1,1,2) do (
REM each time parse 5th element
echo old=!Current_data!
for /F "tokens=5 delims= " %%I in ("!Current_data!") do (
set /a "inew=%%I"
echo inew = !inew!
)
REM Calculate shift needed and next position based on 5th element parsed
Set /a "initial_pos=16"
Set /a "_shift=!inew!*3"
echo _shift=!_shift!
Set /a next_pos=!initial_pos!+!_shift!
echo next_pos=!next_pos!
REM Parse data
Set parsed_data=!Current_data:~%initial_pos%,%_shift%!
echo parsed_data=!parsed_data!
REM Override "Current_data" with the remaining data after sub-stringing "parsed_data"
Set Current_data=!Current_data:~%next_pos%!
echo Current_data=!Current_data!
)
endlocal
You need to make the WHOEL process live inside your First For Loop. Otherwise, it will only ever find the last instance of data=.
REM Exclude "data=" from the text
for /F "tokens=2 delims==" %%B in ('findstr /I "data = " data.txt') do (
set "Current_data=%%B"
)
The Quickest way to handle this and keep sane is to turn the original portion of your script into a function called from within the loop. You can re-work the loops and make it into a smaller tighter code too which would run a little faster, but doing the functions makes the code easier to read and change later if needed.
SO the original script becomes slightly re-written as:
#(SETLOCAL ENABLEEXTENSIONS EnableDelayedExpansion
echo off
SET "_SrcFilePath=C:\Path\To\data.txt"
)
CALL :Main
( ENDLOCAL
Exit /b
)
:Main
REM Exclude "data=" from the text
for /F "tokens=2 delims==" %%B in ('findstr /I "data = " "%_SrcFilePath%"') do (
SET "Current_data=%%B"
CALL :Process
)
GOTO :EOF
:Process
for /L %%s IN (1,1,2) do (
REM each time parse 5th element
echo old=!Current_data!
for /F "tokens=5 delims= " %%I in ("!Current_data!") do (
set /a "inew=%%I"
echo inew = !inew!
)
REM Calculate shift needed and next position based on 5th element parsed
Set /a "initial_pos=16"
Set /a "_shift=!inew!*3"
echo _shift=!_shift!
Set /a next_pos=!initial_pos!+!_shift!
echo next_pos=!next_pos!
REM Parse data
Set parsed_data=!Current_data:~%initial_pos%,%_shift%!
echo parsed_data=!parsed_data!
REM Override "Current_data" with the remaining data after sub-stringing "parsed_data"
Set Current_data=!Current_data:~%next_pos%!
echo Current_data=!Current_data!
)
GOTO :EOF

Compare the absolute value of a number in a for loop to determine if it's to be used?

I'm now on the bigger problem I mentioned in this post...Searching a text file and sending only numbers greater than a certain absolute value to text file?
I figured if I set num=!num:-=! with an original value of, say, -17, then the !errorlevel! will evaluate to true or 0 right? Something's not working here though...
To clarify, I need to filter out only the first and fourth tokens of lines in which the fourth token is either greater than 3 or less than -3, as well as any lines that do not have a 4th token (this part is solved). I have tried using the /A option of set and it doesnt seem to work still.
setlocal enabledelayedexpansion
set "min=-"
for /f "tokens=1,4" %%a in ('findstr /b /r /c:"[^ ]*:S:" print.log') do (
if %%b=="" (echo %%a ^*^*^* >>new.txt) else (
set num="%%b"
set num=!num:-=!
if !errorlevel!==0 (
if !num! GTR 3 echo %%a !min!!num! >> new.txt
) else (
if !num! GTR 3 echo %%a !num! >> new.txt
)
)
)
exit /b
The text in print.log looks like:
ksdf 0 0 -4
as7d:S:asf 0 0 -4
kc:S:cd3 0 0 -2
asdk:S:s 0 0 6
lasd:S:dd 0 0
#echo off
setlocal enableextensions disabledelayedexpansion
>"new.txt" (
for /f "tokens=1,4" %%a in ('
findstr /b /r /c:"[^ ]*:S:" print.log
') do if "%%~b"=="" (echo %%a ***) else (
set "print=1"
if %%b lss 4 if %%b gtr -4 set "print="
if defined print echo %%a %%b
)
)
Instead of printing when the value is lower than -3 OR greater than 3, it does not print when the value is lower than 4 AND greater than -4
-6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6
^.................^
don't print
#ECHO OFF
SETLOCAL EnableExtensions EnableDelayedExpansion
set "threshold=3"
>new.txt (
for /f "tokens=1,4" %%a in ('findstr /b /r /c:"[^ ]*:S:" print.log') do (
if "%%b"=="" (
echo %%a ^*^*^*
) else (
set /A num=%%b
if !num! GEQ 0 (
set "min="
) else (
set "num=!num:-=!"
set "min=-"
)
if !num! GTR %threshold% echo %%a !min!!num!
)
)
)
set /A num=%%b
set num=!num:-=!
This establishes num as the arithmetic value of %%b. Note that environment variables are always strings. The assignment does the conversion each way as required. Your assignment would have assigned a value of (eg) "-4" (including the quotes)
The second command uses the string in num and changes all - to *nothing* hence calculating the absolte-value assuming it's of the appropriate -number structure.
Beyond that, I've no idea what your intentions are to create your output, since you;ve not indicated what the output should be. Either way, errorlevel won't be affected by theset AFAIAA.
Note that %%b will still contain the original number read at the point you are using echo. You can perform an if on %%b as well as on !num! - and use %%b or !num! in your echo as required.
You don't say what your gtr 3 business is designed to do...
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "sourcedir=U:\sourcedir"
SET "filename1=%sourcedir%\q42639932.txt"
FOR /f "tokens=1,4" %%a IN ('findstr /b /r /c:"[^ ]*:S:" "%filename1%"') DO (
if "%%b"=="" (echo %%a ^*^*^*) else (
set num=%%b
set num=!num:-=!
if !num! GTR 3 (echo %%a %%b
) else (
ECHO just FOR demo %%a %%b
)
)
)
GOTO :EOF
You would need to change the setting of sourcedir to suit your circumstances.
I used a file named q42639932.txt containing your data + extras for my testing.
For each line that passes the findstr filter, if column4 is missing, produce asterisks else set num to the value in %%b, and remove any - from it. If the resultant number is >3, echo the original %%b otherwise - well, I've produced a report line for completeness. Obviously, that can be remmed out.

Batch command to find highest number in set of strings?

For instance:
file.txt contains:
4.3 - random1
5.6 - random2
2.2 - random3
3 - random4
1.8 - random5
I need a command that will output the highest number only, not the preceding text.
Ie.
Output = 5.6
You can give SORTN.bat a try.
Here is the code for it as well.
#ECHO OFF
if "%~1"=="/?" (
echo.Sorts text by handling first number in line as number not text
echo.
echo.%~n0 [n]
echo.
echo. n Specifies the character number, n, to
echo. begin each comparison. 3 indicates that
echo. each comparison should begin at the 3rd
echo. character in each line. Lines with fewer
echo. than n characters collate before other lines.
echo. By default comparisons start at the first
echo. character in each line.
echo.
echo.Description:
echo. 'abc10def3' is bigger than 'abc9def4' because
echo. first number in first string is 10
echo. first number in second string is 9
echo. whereas normal text compare returns
echo. 'abc10def3' smaller than 'abc9def4'
echo.
echo.Example:
echo. To sort a directory pipe the output of the dir
echo. command into %~n0 like this:
echo. dir /b^|%~n0
echo.
echo.Source: http://www.dostips.com
goto:EOF
)
if "%~1" NEQ "~" (
for /f "tokens=1,* delims=," %%a in ('"%~f0 ~ %*|sort"') do echo.%%b
goto:EOF
)
SETLOCAL ENABLEDELAYEDEXPANSION
set /a n=%~2+0
for /f "tokens=1,* delims=]" %%A in ('"find /n /v """') do (
set f=,%%B
(
set f0=!f:~0,%n%!
set f0=!f0:~1!
rem call call set f=,%%%%f:*%%f0%%=%%%%
set f=,!f:~%n%!
)
for /f "delims=1234567890" %%b in ("!f!") do (
set f1=%%b
set f1=!f1:~1!
call set f=0%%f:*%%b=%%
)
for /f "delims=abcdefghijklmnopqrstuwwxyzABCDEFGHIJKLMNOPQRSTUWWXYZ~`##$*_-+=:;',.?/\ " %%b in ("!f!") do (
set f2=00000000000000000000%%b
set f2=!f2:~-20!
call set f=%%f:*%%b=%%
)
echo.!f1!!f2!!f!,%%B
rem echo.-!f0!*!f1!*!f2!*!f!*%%a>&2
)
I gave it a try using this input as an example
4.3 - random1
11.3 - random6
5.6 - random2
2.2 - random3
100.1 - random8
3 - random4
1.8 - random5
11.12 - random7
11.11 - random7
This is how I ran it but you should be able to capture the output as well using a FOR /F command just like Stephan showed you in his answer.
type sortme.txt |sortn.bat
Output
1.8 - random5
2.2 - random3
3 - random4
4.3 - random1
5.6 - random2
11.11 - random7
11.12 - random7
11.3 - random6
100.1 - random8
sort will sort in correct order (Attention: this is sorting strings, not numbers, but will work fine for your example. Note that with string comparison 5 or 6.3 are "bigger" than 15).
Put a for around to process the ouput (Standard tokens is 1 and Space is a standard delimiter, so the for /f gets only the first element - your desired number)
for /f %%a in ('sort t.txt') do set high=%%a
echo %high%
EDIT to also process numbers higher than 10. Note: there is no math involved - it's just clever string manipulation.
#echo off
setlocal enabledelayedexpansion
(
for /f "tokens=1,2 delims=. " %%a in (t.txt) do (
set a=0000%%a
if "%%b"=="-" (echo !a:~-4!) else (echo !a:~-4!.%%b)
)
)>temp.txt
type temp.txt
pause
for /f "tokens=1,2 delims=0" %%a in ('sort temp.txt') do set high=%%a
echo %high%
The following script does proper sorting of fractional numbers with eight digits before and after the decimal separator . at most:
#echo off
setlocal EnableExtensions EnableDelayedExpansion
rem // Define constants here:
set "_FILE=%~1" & rem // (input file; `%~1` means first command line argument)
set /A "_ZPAD=8" & rem // (number of zeroes to be used for temporary padding)
set "_ZERO=" & for /L %%K in (0,1,%_ZPAD%) do set "_ZERO=!_ZERO!0"
for /F "usebackq delims=- " %%L in ("%_FILE%") do (
for /F "tokens=1,2 delims=." %%I in ("%%L.") do (
set "INT=%_ZERO%%%I" & set "FRA=%%J%_ZERO%"
set "$NUM_!INT:~-%_ZPAD%!_!FRA:~,%_ZPAD%!=%%L"
)
)
set "MIN=" & set "MAX="
for /F "tokens=2 delims==" %%L in ('2^> nul set $NUM') do (
if not defined MIN set "MIN=%%L"
set "MAX=%%L"
)
echo Minimum: %MIN%
echo Maximum: %MAX%
endlocal
exit /B

Batch command to find a replace string with line break

I have data that is mostly organized in a way that I can convert and import into a spreadsheet. But certain lines have carriage returns and text that my current batch file won't use.
Good Data:
Pipers Cove × 2 $25.00
Pipers Cove Petite × 2 $25.00
Pipers Cove Plus × 2 $25.00
Nordic Club × 2 $25.00
Whiteout × 1 $12.50
Bad Data:
Pipers Cove Kids × 2
Size:
Large - ages 10 to 12
$20.00
Pipers Cove Kids × 2
Size:
Medium - ages 6 to 8
$20.00
Pipers Cove Kids × 2
Size:
Small - ages 2 to 4
$20.00
I need to remove the 2 lines starting with Size, Small, Medium, or Large and have the dollar amount follow the quantity number so my batch file can convert it to a CSV file and so on.
#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
SET "destdir=U:\destdir"
SET "filename1=%sourcedir%\q40953616.txt"
SET "outfile=%destdir%\outfile.txt"
SET "part1="
(
FOR /f "usebackqdelims=" %%i IN ("%filename1%") DO (
ECHO %%i|FIND "$" >NUL
IF ERRORLEVEL 1 (
REM $ not found - set part1 on first such line
IF NOT DEFINED part1 SET "part1=%%i"
) ELSE (
REM $ found - see whether at start or not
FOR /f "tokens=1*delims=$" %%a IN ("%%i") DO (
IF "%%b"=="" (
REM at start - combine and output and reset part1
CALL ECHO %%part1%% %%i
SET "part1="
) ELSE (
ECHO %%i
)
)
)
)
)>"%outfile%"
GOTO :EOF
You would need to change the settings of sourcedir and destdir to suit your circumstances.
I used a file named q40953616.txt containing your data for my testing.
Produces the file defined as %outfile%
Scan each line of the file. If the line does not contain $ then save the first such line in part1.
Otherwise, tokenise the line. If there is only 1 token, then the $ is at the start of the line, so it needs to be output combined with part1
Otherwise, just regurgitate the line.
Although you did not show any own efforts, I decided to provide a solution as the task at hand appears not that trivial to me.
The following script -- let us call it clean-up-text-file.bat -- ignores only lines that begin with the words you specified. Any other lines are appended to the previous one until a $ sign is encountered, in which case a new ine is started. With this method, no lines can get lost unintentionally.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set _WORDS="Size","Small","Medium","Large"
for %%F in (%*) do (
set "COLL=" & set "FILE=%%~F"
for /F delims^=^ eol^= %%L in ('type "%%~F" ^& ^> "%%~F" rem/') do (
set "LINE=%%L"
(echo("%%L" | > nul find "$") && (
setlocal EnableDelayedExpansion
>> "!FILE!" echo(!COLL!!LINE!
endlocal
set "COLL="
) || (
set "FLAG="
for %%K in (%_WORDS%) do (
(echo("%%L" | > nul findstr /I /R /B /C:^^^"\"%%~K\>") && (
set "FLAG=#"
)
)
if not defined FLAG (
setlocal EnableDelayedExpansion
rem // The following line contains a TAB character!
for /F "delims=" %%E in (^""!COLL!!LINE! "^") do (
endlocal
set "COLL=%%~E"
)
)
)
)
)
endlocal
exit /B
To use the script, provide your text file(s) as (a) command line argument(s):
clean-up-text-file.bat "good.txt" "bad.txt"
Every specified file is modified directly, so take care when testing!

Resources