5

I need a batch script for windows that does the following:

  1. dumps all the filenames from a directory to a .txt file (usually several hundred up to 50ish thousands of files)
  2. searches the output file for particular strings (around 35 of these), counts them and creates another file with the results

Given that I didn't script a thing before today, I came up with the following:

@echo off  
dir /b > maps.txt  
(  
find /c /i "string1" maps.txt  
find /c /i "string2" maps.txt  
...  
find /c /i "string35" maps.txt  
)  > results.txt  

The result is promising, but I would need the strings enumerated in the results.txt file, along with the count, so that the results file would look like this:

string1 = 3  
string2 = 5  
...  
string35 = 1 

A .csv file would also be OK, in which case I would need the following format:

string1;3  
string2;5  
...  
string35;1  

Is such thing possible?

3
  • You provided plenty of info, so no worries for your first question (IMO). Usually it's just "I need a script that does X." which are then closed. +1 for showing you attempted something! :) Oct 23, 2015 at 13:04
  • The "SORT" command might be helpful. The format you suggest is not .csv ("comma separated value"), it looks like .ssv ("semi-colon"-separated value).
    – TOOGAM
    Oct 23, 2015 at 13:18
  • "SORT" would not help me - or rather - it might help later on. What I'm looking for now is 'linking' the string to the count, as for this moment, the results.txt file looks like this: ---------- MAPS.TXT: 3 ---------- MAPS.TXT: 1 And I would need to replace instances of "---------- MAPS.TXT" with the actual strings that are counted at that time. Can the 'find' command be combined with 'echo' in a different way? Or maybe I need a different method of counting? Oct 23, 2015 at 13:45

1 Answer 1

3

Total String Counts Per String

Batch Script (implicit)

@ECHO OFF

::: If this file exists, delete it 
IF EXIST "Results.txt" DEL /Q /F "Results.txt"

::: Bare format DIR command listing ONLY filename.extension 
DIR /B > maps.txt

::: Please go to command line and type FOR /? and look through there for the FOR /F explanations
::: This is saying for each line in strings.txt do a FIND /I for each string in maps.txt and if FIND /I finds a string, then CALL the StringCountRoutine and pass the string found as the first argument to the CALL :label (:StringCountRoutine in this instance)
::: Please note that is a string IS NOT FOUND then there will be no count and not a zero unfortunately so it's implied that is the string is not in the results.txt file, then the count of that string is zero
FOR /F "TOKENS=*" %%S IN (Strings.txt) DO (FIND /I "%%S" maps.txt && CALL :StringCountRoutine "%%~S")
::: GOTO EOF needed here to pass control back to the CALLER or END once loop is complete to it doesn't move on to logic beneath which should only be called
GOTO EOF

:StringCountRoutine
::: This is saying the TOKEN count is three and each token to count (the DELIMITER) are colons and spaces ("DELIMS=: ") so for example this (---------- MAPS.TXT: 14) has two spaces and one colon so only have the variable be what's left afterwards which is just the number when set this way
::: The first argument is passed to the FIND /C command as listed below and also the ECHO command afterwards
FOR /F "TOKENS=3DELIMS=: " %%A IN ('FIND /C "%~1" maps.txt') DO (ECHO %~1 = %%A >> Results.txt)
::: GOTO EOF needed here to pass control back to the CALLER or END once loop is complete to it doesn't move on to logic beneath which should only be called
GOTO EOF

Search Strings in a File and Find the same Strings in Another File

Below are two examples showing a way to do what you need I believe but you'd want to save your string values to a separate text file where each string is represented per line in that file. As long that the TOKENS=* is in the FOR /F line, it'll read each line with or without spaces as the string value you're looking for in the map.txt file.

Implicitly Defined Script

@ECHO OFF

::: If this file exists, delete it 
IF EXIST "Results.txt" DEL /Q /F "Results.txt"

::: Bare format DIR command listing ONLY filename.extension 
DIR /B > maps.txt

::: Set seq variable to 1 for the first sequence number
SET seq=1

::: Please go to command line and type FOR /? and look through there for the FOR /F explanations
::: This is saying for each line in strings.txt do a FIND /I for each string in maps.txt and if FIND /I finds a string, then CALL the SeqAdditionRoutine and pass the string found as the first argument to the CALL :label (:SeqAdditionRoutine in this instance)
FOR /F "TOKENS=*" %%S IN (Strings.txt) DO (FIND /I "%%S" maps.txt && CALL :SeqAdditionRoutine "%%~S")
::: GOTO EOF needed here to pass control back to the CALLER or END once loop is complete to it doesn't move on to logic beneath which should only be called
GOTO EOF

:SeqAdditionRoutine
::: This is saying FIND /I but with first argument passed as the string (same as above FIND /I but the first argument is passed here), and if successful (the double AND) ECHO the string equals 1 (or the sequence number variable value) to results.txt
FIND /I "%~1" maps.txt && ECHO %~1 = %seq% >> results.txt
::: This is saying (see SET /?) whatever seq variable is set to, ADD one to it and set it to this new value for whatever adding one to it will make it when it goes to EOF, it'll loop the next command (the CALLing loop) with this new value until it is successful in finding a strings and comes back down here again
SET /A seq=%seq%+1
::: GOTO EOF needed here to pass control back to the CALLER or END once loop is complete to it doesn't move on to logic beneath which should only be called
GOTO EOF

Explicitly Defined Script

@ECHO OFF

SET stringlist=C:\folder\folder\Strings.txt
SET mapsfile=C:\folder\folder\Maps.txt
SET resultsfile=C:\folder\folder\Results.txt

IF EXIST "%resultsfile%" DEL /Q /F "%resultsfile%"

DIR /B > "%mapsfile%"

SET seq=1
FOR /F "TOKENS=*" %%S IN (%stringlist%) DO (FIND /I "%%S" "%mapsfile%" && CALL :SeqAdditionRoutine "%%~S")
GOTO EOF

:SeqAdditionRoutine
FIND /I "%~1" "%mapsfile%" && ECHO %~1 = %seq% >> "%resultsfile%"
SET /A seq=%seq%+1
GOTO EOF

Update

I tested this from the implicit script and it worked as expected. . .

I only got the string = number for only those strings found to match in the Strings.txt and not any from the maps.txt or other txt files in that same directory.

The strings I defined in the Strings.txt file did contain numbers so with FIND /V I did notice that string1 also matched string10 and string11 as in my example. I'm not sure if this would be an issue for you or not or what values would match your search string value criteria but this may be something to consider when you apply. I'm not certain if FINDSTR /L or FINDSTR /I /C:"%~1" would be better or not.

5
  • Thanks for help, but this does not give me the output I need (unless I need to amend anything in Implicit version of the script). The test run on my desktop with 8 .txt files and .txt string in the Strings.txt file gives me a result of ".txt = 1" :( So, the listing of actual strings seem to work, but counting them does not work, unfortunately. As I mentioned originally, I'm new to scripting, so I don't know how to combine both - I would appreciate further help (and rather if it was a guidance, not actual script, so that I can learn a bit or, at least, understand what is going on). Oct 26, 2015 at 10:24
  • Thanks again, this is still not what I need, unfortunately. The script you wrote for me checks if the strings from strings.txt file exist in maps.txt, and if yes, gives them particular number, while I need to count the occurences of each string in the maps.txt - my original short script does that, but echoes the results as: ---------- MAPS.TXT: 8 ---------- MAPS.TXT: 16 ---------- MAPS.TXT: 0 ---------- MAPS.TXT: 10 etc. (8 occurances of string1, 16 occurances of string2, 0 occurances of string3, 10 occurances of string4). (TBC in next comment) Oct 26, 2015 at 21:50
  • (CONTINUED) Is there a way to echo the result as: string1: 8 string2: 16 string3: 0 string4: 10 etc. ? Do i need to work with the ECHO command instead of going with FOR and tokens? Or maybe I need to combine those in a different way? Would find /c /i "string1" maps.txt && ECHO string1 = ? >> results.txt work if I added something instead of "?" ? Oct 26, 2015 at 21:59
  • @MateuszWatmanWata see the TOTAL STRING COUNT PER STRING section instead, I reformatted it so the exact answer is up top and the rest is bonus as-needed for you and others. Good Luck!! Oct 26, 2015 at 23:43
  • Thank you! The final update works as expected and is exactly what I need! Kudos to you! Oct 27, 2015 at 7:37

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .