How to compare the text lines from two files in batch - batch-file

That is the identical content of my 2 txt files formatliste_droid.txt and formatliste_siegfried.txt. I want to know if all the lines till delimiter $:$ are identical 1-1, 2-2 and so on.
Z:\15_Testdateien\jhove_Script_fuer_MIX-Verzeichnisse\testfiles\BVBBV042064787\Files\E\images.jpg$;$fmt/43
Z:\15_Testdateien\jhove_Script_fuer_MIX-Verzeichnisse\testfiles\BVBBV042064787\Files\E\Van Schijndel House - English.mp4$;$fmt/199
Z:\15_Testdateien\jhove_Script_fuer_MIX-Verzeichnisse\testfiles\BVBBV042064787\Files\E\Van Schijndelhuis - Nederlands.mp4$;$fmt/199
That's my code:
#echo off
Setlocal EnableDelayedExpansion
for /f "tokens=1 delims=$;$" %%a in (formatliste_siegfried.txt) do (
for /f "tokens=1 delims=$;$" %%c in (formatliste_droid.txt) do (
if /i %%a==%%c (
echo match
pause
)
)
)
The problem is that I always get a match even if the appropriate lines are not identical

TL;DR -
Use the fc.exe command.
Details -
There are a few issues with this logic preventing you from getting the output you're looking for. The reason you only get "match" for output is because that is the only possible output - there's only one "echo" line. Adding a case else would output the number of times a line doesn't match.
That said, adding the else would be too noisy to be valuable since the large majority of the output would be "doesn't match". The logic here says "for each line of file 1, check every single line of file 2 to check for a match". For example: given 2 files which each have 100 lines, even if each line had a match in the other file, for each of the 100 outer loops, the output would be 1 "match" and 99 "doesn't match". I'll assume you don't want 100 "match" and 9900 "doesn't match".
So instead, and still considering the question being "how to compare the text lines from two files", I'd recommend using the FC.exe command. Whether batch or vanilla command line, it was designed to compare files.
Other items for consideration:
Missing double quotes around comparison items containing spaces
%%a==%%c ... should be... "%%a"=="%%c"
"delims=" can match nearly any single character, but never a contiguous multi-character group
"Setlocal EnableDelayedExpansion" isn't required as there's no dynamic use of "set"
if case is important, the use of "if /i" will break the integrity of the check

Related

How to output multiple lines from a FINDSTR to a variable

It's no surprise that the official documentation doesn't really help in the matter of understanding how does the command process the result of a command instead of a filelist neither why is it even called 'FOR'. Yes I already know Stack Overflow is full of similar question but apparently, since batch scripts are influenced by so many
"breaking" factors that, even as a non-batch experienced programmer, it is difficult not to get lost in the thousands exceptions and do-nots which may affect the result.
My objective, aside from learning from the best answer possible, is to formulate a generic enough question to represent the matter which is probably the most common task including the FINDSTR command:
THE QUESTION:
How do I get the output of a FINDSTR in a way that allows me to compute every result line one at the time
possibly INSIDE the loop?
The most 'generic' (batch bs-proof if you know what I mean) example I can make is the following:
Let's say this is secret_file.txt
some not interesting line
A very interesting line = "secret1";
some not interesting line
A very interesting line = "secret2";
some not interesting line
A very interesting line = "secret3";
some not interesting line
Now with the findstr command I can output every "secret" line like this:
findstr /R /C:"secret.\"" secret_file.txt
A very interesting line = "secret1";
A very interesting line = "secret2";
A very interesting line = "secret3";
But this result is just useless without further parsing right? I could have used ctrl-F over any text reader/editor
for this matter, anyway, let's say I now want to output every line ONE AT THE TIME so that I can compute it, for
example, saving every secret to a variable then using that variable somehow
(it doesn't really matter how, we can just echo it to keep things simple).
Now, everybody agrees on the fact that for this kind of task, a FOR loop is needed.
Quoting https://ss64.com/nt/for.html on the syntax, my script.bat should looks like this:
#echo off
FOR /F %%A IN ('findstr /R /C:"secret.\"" secret_file.txt') DO ECHO Batch script language is completely fine, good job Microsoft!
This just doesn't even give any output, can someone explain me why? My hypothesis was that the output from the findstr command
is in a non-compatible format with the FOR command, not like I could check or something since the source is closed and the
documentation doesn't even bother defining the word String.
I'm ready to provide any details and even edit the question to be more visible to the wanna be Microsoft-forsaken batch scripters out there.
Using "tokens=*" to strip off leading spaces this batch uses a counter to create a (pseudo) array secret[]
:: Q:\Test\2018\12\04\SO_53614102.cmd
#Echo off
set Cnt=0
FOR /F "tokens=*" %%A IN (
'findstr /R /C:"secret.\"" secret_file.txt'
) DO (
set /a Cnt+=1
call Set Secret[%%Cnt%%]=%%A
)
Set Secret[
Sample output:
> SO_53614102.cmd
Secret[1]=A very intersting line = "secret1";
Secret[2]=A very intersting line = "secret2";
Secret[3]=A very intersting line = "secret3";
As variables in a (code block) are expanded at parse time,
delayed expansion is requiered (here through a call and doubled %%)

inverted question mark and findstr

I can't seem to write certain characters (inverted question marks, fancy single quote marks, ampersands) to a text file, and then to search that file for those characters. For example the following findstr doesn't find the upside down question mark item in .txt:
#echo off
echo "Cato Event - GO Beyond GDP. What Really Drives the Economy¿">c:\test.txt
findstr /I /N /C:"Cato Event - GO Beyond GDP. What Really Drives the Economy¿" c:\test.txt
pause
::chcp 1254
I've tried with various chcp commands also to no avail.
Any help appreciated.
That is a known issue with FINDSTR - Some characters provided on the command line with ANSI byte codes > 127 are transformed into a different character by FINDSTR, prior to doing the search, which causes the search to fail.
The solution is to put the search string(s) in a file and use the /L and /G options.
See the section titled "Character limits for command line parameters - Extended ASCII transformation" at What are the undocumented features and limitations of the Windows FINDSTR command?
The only other option (assuming you want to stick with native batch commands) is to use FIND instead. It has much less functionality, but it does not have the character translation issue, and I believe it should work for your simple literal search.
find /I /N "Cato Event - GO Beyond GDP. What Really Drives the Economy¿" c:\test.txt
The line numbers at the beginning of each matching line will look like [123] instead of 123:.

Storing multi-word strings to a file

I've recently been trying to make a program to simply store text to a file for later viewing, storing it as a .rar file for security against those who don't understand how to extract the text from the .rar (i.e. the less "techy" people)...
I have, however, encountered an error in the program that results in the <word> not expected at this time followed by the .exe closing when I input add/<word> <word>... (i.e. any multi-word string with spaces in between the words [add/<word>, however, does function properly]).
Is there a special rule that must be followed for storing multi-word strings to a .rar or a file in general (I do, however, know that there is a rule for creating/renaming folders/directories)?
The Program Segment:
:command
cls
set /p journal=<journal.rar
echo %journal%
echo.
set /p command=What would you like to do?
cls
if %command%==exit exit
if %command%==help goto help
if %command%==delete echo START; > journal.rar
if %command:~0,4%==add/ echo "%journal%""%command:~4%;" > journal.rar
if %command:~0,5%==edit/ echo %journal:%command:~5%=%;" > journal.rar
goto command
Excuse me. Your question is not clear. There are several confusing points in it, like "followed by the .exe closing" (which .exe is closing?), and the fact that your question is NOT related to .rar files in any way, nor to "storing multi-word strings". However, I can see the following points in it:
When a variable value is expanded with percent signs this way: %command% you must be aware that the variable is first expanded and then the resulting line is parsed. This mean that the value of the variable may introduce errors in the line. For example, in this line: if %command%==exit exit, if the value of command variable is add/one two three, then the line that is parsed is this: if add/one two three==exit exit that, of course, issue an error! (type if /? for further details).
The way to avoid this problem is enclosing both the variable and the comparison value in quotes; this way, if the value have several words with spaces, the whole value is grouped in the IF command for comparison purposes: if "%command%" == "exit" exit. This must be done in every IF command that use the value of the variable.
In the following line:
if %command:~0,5%==edit/ echo %journal:%command:~5%=%;" > journal.rar
you must be aware that the line is parsed from left to right; this means that you can not nest a %variable% expansion inside another one. The way to solve this problem is first complete a %normal% variable expansion, and then a !delayed! variable expansion that will take the previous expanded value. To do that, insert this line at beginning of your program:
setlocal EnableDelayedExpansion
and change previous line by this one:
if "%command:~0,5%" == "edit/" echo !journal:%command:~5%=!;" > journal.rar
For further details, type set /? and carefully read the sections about "delayed expansion".
Here is a sample that can accept multiple words:
set "command="
set /p "command=What would you like to do? "
cls
if /i "%command%"=="have lunch" goto :food

Windowes Batch file: find line with specifies words

I have to run script that find find partition with more than 1 GB free space.
I wrote the following:
#echo on
set isComplete = 0
set last = 0;
DISKPART /s .\script.txt > .\log.txt
for /f "tokens=3" %%f in ('.\log.txt') do (
FIND /C /I "GB" .\log.txt > %isComplete%
IF %isComplete% > 0
%last% = %%f
)
Dispart call to another script that prints to log.txt all the availble partitions.
Log.txt equals to:
Partition ### Type Size Offset
Partition 1 Primary 74 GB 1024 KB
Partition 2 Primary 300 MB 74 GB
now, i want to check which parttion has more than 1 GB free space, so I look foe "GB" word.
but I always get: > "was unexpected at this time." error.
can anyine help me to figure out what the problem? or suggest me a better way to do that?
thanks!!!
Ouch.
You've got a number of problems.
The output of LIST PARTITION gives the size and offset of each partition. I'm not very familiar with DISKPART, but I don't believe the size gives the amount of free space within the partition. It indicates how large the partition is, but gives no indication of how much space has already been allocated to existing files. The offset indicates the location of the partition. So it seems you are off on the wrong foot right from the get-go.
That being said, you have some major syntax problems in your script.
It looks like you are trying to read a file in your FOR statement, but in reality your syntax is attempting to execute a command because you enclosed the file name in single quotes. You need to type HELP FOR from the command line and read carefully the description of the FOR command.
You want either
for /f "tokens=3" %%f in (log.txt) do (
or, if the filename contains spaces (which yours doesn't), then
for /f "usebackq tokens=3" %%f in ("file name with spaces.txt") do (
Your line FIND /C /I "GB" .\log.txt > %isComplete% is attempting to write the output of the FIND command to a file named "0". I doubt that is your intention. The FIND command will print out the complete text of any line that contains your search string of "GB". It will also set the ERRORLEVEL to 0 if it finds at least one matching line, or 1 if it fails to find a matching line. I'm not sure what you are attempting to do.
Your IF statement is a mess. Here again you need to type HELP IF from the command line and read carefully how to use it. Your existing attempt has many errors
You can't extend an IF statement accross multiple lines unless you either use line continuation ^, or parentheses.
You can't use > as a comparison operator, you need to use GTR
I can't figure out exactly what comparison you are trying to make.
I don't know how to point you in the right direction because I don't understand what your overall mission is. Perhaps if you describe in more detail what you are trying to do, someone can provide a script that will accomplish the task, and you can learn from that example.
DISKPART is a potentially dangerous tool. I don't see how you can do harm with the LIST command, but other commands could create problems if misused. While you are learning the rudiments of batch scripting, I suggest you avoid DISKPART. I would hate for you to accidently corrupt your hard drive because of a batch programming mistake.

Batch program script problem breaks with file names with spaces

The following is a batch script that calls mp3splt (a program that splits mp3s http://mp3splt.sourceforge.net/mp3splt_page/home.php) into partitions of 5 mins long.
for /f %%a IN ('dir /b *.mp3') do call c:\PROGRA~1\mp3splt\mp3splt -t 5.0 -o output\#f+-+#n+-+#t %%a
It breaks when the mp3 files contain a space. Can anyone propose a workaround?
for %%a IN (*.mp3) do (
call c:\PROGRA~1\mp3splt\mp3splt -t 5.0 -o output\#f+-+#n+-+#t "%%a"
)
What others are saying here to quote the variable is doubtless correct. That's needed for it to work correctly. But it also is only half the solution.
Your problem here is that dir /b spits out lines of text, each one containing a single file name, like so:
foo bar.mp3
baz gak.mp3
track01.mp3
...
for /f on the other hand is made for reading files or something else (the dir output in this case) line by line ... but it also does tokenizing. That means it splits strings at configurable places into individual tokens.
By default, /F passes the first blank
separated token from each line of each
file. Blank lines are skipped. You
can override the default parsing
behavior by specifying the optional
"options" parameter. This is a quoted
string which contains one or more
keywords to specify different parsing
options. —help for
So you only get the part before the first space of the file name. You can work around that by using
for /f "delims=" in ...
to specify that tokenizing should be done with no delimiters, essentially giving you the complete line each time. But a better way is actually the one I outlined at the start to just use the regular for to iterate over the files. No surprises with spaces in file names there and it actually makes your intent a lot clearer.
I am regularly surprised why people tend to choose a convoluted and wrong solution over a simple, clear and correct one.
You can quote the variable containing the file name:
"%%a"

Resources