count number of rows per text file using batch file - windows

I have this batch command that counts the number rows per log/text file. If I have a text file that has 3 or more rows meaning my md5deep verification has a mismatch. The problem is I have multiple folders with CheckMismatch.txt. I am looking for a looping that will CHECK all CheckMismatch.txt and count the rows one by one.
IF EXIST C:\BACKUPS\WEBAPP-UAT\WEBAPP\FOLDER1 (md5deep64 -x "C:\BACKUPS\WEBAPP-UAT\WEBAPP\FOLDER1\FOLDER1.md5" -r "C:\BACKUPS\WEBAPP-UAT\WEBAPP\FOLDER1" > C:\BACKUPS\WEBAPP-UAT\WEBAPP\FOLDER1\CheckMismatch.txt
#echo off
setlocal EnableDelayedExpansion
set "cmd=findstr /R /N "^^" C:\BACKUPS\WEBAPP-UAT\WEBAPP\FOLDER1\CheckMismatch.txt | find /C ":""
for /f %%a in ('!cmd!') do set number=%%a
if %number% gtr 2 (echo there is a mismatch in FOLDER1) ELSE (echo FOLDER1 HASHES matched)
)
Folder1
CheckMismatch.txt
Folder2
CheckMismatch.txt
Folder3
CheckMismatch.txt
Folder4
CheckMismatch.txt
Folder5
CheckMismatch.txt

There is no need for FINDSTR before FIND. You can count the rows directly with FIND alone. And you can use FINDSTR to test if the count is less than or equal to 2. This enables you to use && and || instead of IF.
If you want to process a fixed list of folders under "C:\BACKUPS\WEBAPP-UAT\WEBAPP\"
#echo off
setlocal
set "root=C:\BACKUPS\WEBAPP-UAT\WEBAPP"
for %%F in (
Folder1
Folder2
Folder3
Folder4
Folder5
) do (
md5deep64 -x "%root%\%%F\%%F.md5" -r "%root%\%%F" >"%root%\%%F\CheckMismatch.txt"
type "%root%\%%F\CheckMismatch.txt" | find /c /v "" | findstr /x "0 1 2" && (
echo There is a mismatch in %%F
) || (
echo %%F hashes matched
)
)
It is more likely that you want to process all folders under "C:\BACKUPS\WEBAPP-UAT\WEBAPP\"
#echo off
for /d %%F in ("C:\BACKUPS\WEBAPP-UAT\WEBAPP\*") do (
md5deep64 -x "%%F\%%~nxF.md5" -r "%%F" >"%%F\CheckMismatch.txt"
type "%%F\CheckMismatch.txt" | find /c /v "" | findstr /x "0 1 2" && (
echo %%~nxF hashes matched
) || (
echo There is a mismatch in %%~nxF
)
)
If CheckMismatch.txt is just a temporary file that you don't need later on, then you can avoid creation of the file entirely
#echo off
for /d %%F in ("C:\BACKUPS\WEBAPP-UAT\WEBAPP\*") do (
md5deep64 -x "%%F\%%~nxF.md5" -r "%%F" | find /c /v "" | findstr /x "0 1 2" && (
echo %%~nxF hashes matched
) || (
echo There is a mismatch in %%~nxF
)
)

There was a delayed expansion problem (using %number% in a code block instead of !number!)
Tried to format more clearly.
#Echo off
SetLocal EnableExtensions EnableDelayedExpansion
Set "Folder=C:\BACKUPS\WEBAPP-UAT\WEBAPP\FOLDER1
IF EXIST "%Folder%" (
md5deep64 -x "%Folder%\FOLDER1.md5" ^
-r "%Folder%" > "%Folder%\CheckMismatch.txt"
set "cmd=findstr /R /N "^^" "%Folder%\CheckMismatch.txt" | find /C ":""
Set "number=0"
for /f %%a in ('!cmd!') do set number=%%a
if !number! gtr 2 (
echo there is a mismatch in FOLDER1
) ELSE (
echo FOLDER1 HASHES matched)
)
)

Related

Batch Script Iterative form

I have a batch script which :
check the files in a directory and check if it exists in another
directory and it should not exists there
count each file with a specific format, there should be just one of each
if both of the above statement is true then generate a success file.
Below is my code which is working fine:
SET /A file1=file2=Val=0
SET /A FileE=1
set /a flagname=1
for %%A in (*ABC*.txt) do set /a file1+=1
for %%A in (*XYZ*.txt) do set /a file2+=1
for %%i in ("*") do if exist "Processed\%%~nxi" SET /A FileE=0
SET /A Val=%file1%*%file2%*%FileE%
if %Val% EQU 1 (
echo SUCESS>Sucess.txt
SET Flag=Sucess
echo %Flag%) else (
if %file1% EQU 0 ( echo Missing ABC.txt files >> Error.txt)
if %file1% GTR 1 ( echo More than 1 ABC.txt files >> Error.txt)
if %file2% EQU 0 ( echo Missing XYZ.txt files >> Error.txt)
if %file2% GTR 1 ( echo More than 1 XYZ.txt files >> Error.txt)
(for %%i in ("*") do if exist "Processed\%%~nxi" echo(File Exists in
Processed
Folder %%~i)>>Error.txt
SET Flag=FAILURE
echo %Flag%)
My problem is how to transform above code to iterate over a list of number of files like 100 ? Below is the code which I tried :
#echo off
setlocal enable delayed expansion
Set Filen[0]=ABC*.txt
Set Filen[1]=XYZ*.txt
SET /A Val=1
SET /A File1=0
FOR /l %%G in (0,1,1) Do (
echo !Filen[%%G]! hi
set File1=0
echo %file1% Count
for %%A in (!Filen[%%G]! ) do (
set File1=!File1!+1
echo %%A %file1%)
)
Put your search words in a string and iterate over it:
Set "Search=ABC DEF XYZ"
For %%A in (%Search%) do (
Or in a file and read one by one
For /f "usebackq" %%A in ("Search.txt") Do (
With this file Search.txt
ABC
DEF
XYZ
In the environment
> tree a:\ /F
Auflistung der Ordnerpfade für Volume RamDisk
A:\
└───Test
│ ABC_123.txt
│ DEF_456.txt
│ Search.txt
│
└───Processed
The following batch
:: Q:\Test\2018\07\01\SO_51120147.cmd
#Echo off & Setlocal EnableDelayedExpansion
Set "BaseDir=A:\Test"
Set Err=^>^> "Error.txt" Call Echo=[%%date%% %%time%%]
PushD "%BaseDir%" || (%Err% can't locate %BaseDir% & Pause &Goto :Eof)
%Err% Job %~f0 started by %USERNAME%
Set " Flag=Sucess"
:: Uncomment for string variant
:: Set "Search=ABC DEF XYZ"
:: For %%A in (%Search%) do (
:: use the file variant
For /f "usebackq" %%A in ("Search.txt") Do (
Set Cnt=0
For %%B in (%%A*.txt) Do Set /A Cnt=1
if !Cnt! NEQ 1 (
%Err% Count of %%A*.txt file=[!Cnt!]
SET Flag=FAILURE
)
)
For %%A in (*) do if exist "Processed\%%~nxA" (
%Err% File %%A does exist in Processed Folder
Set Flag=FAILURE
)
%Err% Job %~f0 terminated with %Flag%
Yields this output:
> type A:\Test\Error.txt
[2018-07-01 13:10:34,43] Job Q:\Test\2018\07\01\SO_51120147.cmd started by LotPings
[2018-07-01 13:10:34,45] Count of XYZ*.txt file=[0]
[2018-07-01 13:10:34,47] Job Q:\Test\2018\07\01\SO_51120147.cmd terminated with FAILURE
EDIT: Explanation of the somehow tricky line:
Set Err=^>^> "Error.txt" Call Echo=[%%date%% %%time%%]
To not have to pre/append every line which should go to the error log with
the redirection and a (fixed) file name I put these together with the
echo command and a [date time] stamp into a variable.
To avoid immediate interpretation when setting the variable, the '>' have to
be esaped with a caret, and to delay the expansion of the %-signs these have
to be doubled. (otherwise each log entry had the same date time)
To force expansion of date time when echoing the (pseudo) call is neccessary.

Find string in multiple .txt files

I have a folder with many .txt files. I would like to find string "X" in all of these files then I would like to copy the found strings into .txt files into a different folder.
So far I have tried :
#echo on
findstr /m "X" "%userprofile%\Desktop\New_Folder\New_Folder\*.txt"
if %errorlevel%==0 do (
for %%c in (*.txt) do (
type %%c >> "%UserProfile%\Desktop\New_Folder\%%~nc.txt"
pause
I do not understand the output %%~nc.txt part it's suppost to copy the changed .txt files to a new folder with the same name.
I would like to point out that string "X" is found in different places in the .txt file.
This batch file can did the trick (-_°)
So, just give a try : ScanfilesWordSearch_X.bat
#ECHO OFF
::******************************************************************************************
Title Scan a folder and store all files names in an array variables
SET "ROOT=%userprofile%\Desktop"
Set "NewFolder2Copy=%userprofile%\Desktop\NewCopyTxtFiles"
SET "EXT=txt"
SET "Count=0"
Set "LogFile=%~dp0%~n0.txt"
set "Word2Search=X"
SETLOCAL enabledelayedexpansion
REM Iterates throw the files on this current folder and its subfolders.
REM And Populate the array with existent files in this folder and its subfolders
For %%a in (%EXT%) Do (
Call :Scanning "%Word2Search%" "*.%%a"
FOR /f "delims=" %%f IN ('dir /b /s "%ROOT%\*.%%a"') DO (
( find /I "%Word2Search%" "%%f" >nul 2>&1 ) && (
SET /a "Count+=1"
set "list[!Count!]=%%~nxf"
set "listpath[!Count!]=%%~dpFf"
)
) || (
( Call :Scanning "%Word2Search%" "%%~nxf")
)
)
::***************************************************************
:Display_Results
cls & color 0B
echo wscript.echo Len("%ROOT%"^) + 20 >"%tmp%\length.vbs"
for /f %%a in ('Cscript /nologo "%tmp%\length.vbs"') do ( set "cols=%%a")
If %cols% LSS 50 set /a cols=%cols% + 20
set /a lines=%Count% + 10
Mode con cols=%cols% lines=%lines%
ECHO **********************************************************
ECHO Folder:"%ROOT%"
ECHO **********************************************************
If Exist "%LogFile%" Del "%LogFile%"
rem Display array elements and save results into the LogFile
for /L %%i in (1,1,%Count%) do (
echo [%%i] : !list[%%i]!
echo [%%i] : !list[%%i]! -- "!listpath[%%i]!" >> "%LogFile%"
)
(
ECHO.
ECHO Total of [%EXT%] files(s^) : %Count% file(s^) that contains the string "%Word2Search%"
)>> "%LogFile%"
ECHO(
ECHO Total of [%EXT%] files(s) : %Count% file(s)
echo(
echo Type the number of file that you want to explore
echo(
echo To save those files just hit 'S'
set /p "Input="
For /L %%i in (1,1,%Count%) Do (
If "%INPUT%" EQU "%%i" (
Call :Explorer "!listpath[%%i]!"
)
IF /I "%INPUT%"=="S" (
Call :CopyFiles
)
)
Goto:Display_Results
::**************************************************************
:Scanning <Word> <file>
mode con cols=75 lines=3
Cls & Color 0E
echo(
echo Scanning for the string "%~1" on "%~2" ...
goto :eof
::*************************************************************
:Explorer <file>
explorer.exe /e,/select,"%~1"
Goto :EOF
::*************************************************************
:MakeCopy <Source> <Target>
If Not Exist "%~2\" MD "%~2\"
Copy /Y "%~1" "%~2\"
goto :eof
::*************************************************************
:CopyFiles
cls
mode con cols=80 lines=20
for /L %%i in (1,1,%Count%) do (
echo Copying "!list[%%i]!" "%NewFolder2Copy%\"
Call :MakeCopy "!listpath[%%i]!" "%NewFolder2Copy%">nul 2>&1
)
Call :Explorer "%NewFolder2Copy%\"
Goto:Display_Results
::*************************************************************
#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
SET "destdir=U:\destdir"
SET "mystring=x"
FOR %%a IN ("%sourcedir%\*.txt") DO FINDSTR "%mystring%" "%%a">nul&IF NOT ERRORLEVEL 1 FINDSTR "%mystring%" "%%a">"%destdir%\%%~nxa"
GOTO :EOF
You would need to change the settings of sourcedir and destdir to suit your circumstances and set mystring appropriately, noting that you may have to adjust the findstr switches to accomodate case, literal and space-in-target-string.
Naturally, you could code sourcedir etc. directly as literals, but doing it this way means that the relevant strings need only be changed in one place.
You are close, but checking the ErrorLevel of findstr does not make sense here as this reflects the overall result, that is, ErrorLevel is set to 0 in case any of the files contain the search string.
I would parse the output of findstr /M using a for /F loop and copy the returned files in the body:
for /F "eol=| delims=" %%F in ('
findstr /M /I /C:"X" "%USERPROFILE%\Desktop\New_Folder\New_Folder\*.txt"
') do (
copy "%%F" "%USERPROFILE%\Desktop\New_Folder\"
)
This copies all those files which contain the literal search string (in a case-insensitive manner).

FINDSTR Result issue in Batch File

I want to search all files in a certain directory and print results in text file.
But i want results in separated by '|' based on file name.
Example.
My Input files are
A.txt and B.txt etc...
My Batch Script
#echo off
setlocal
pushd D:\Source
findstr /c:"Apple" /c:"Banana" /c:"Grapes" *.txt > Results.txt
popd
endlocal
Results are coming like this
a.txt Apple
a.txt Banana
b.txt Banana
b.txt Grapes
But i want result like this
a.txt Apple|Banana
b.txt Banana|Grapes
HOW TO GET HELP!!
#ECHO OFF
SETLOCAL enabledelayedexpansion
SET "sourcedir=c:\sourcedir\abg"
SET "resultfile=results.xtx"
pushd %sourcedir%
DEL %resultfile% 2>nul
SET "filename="
FOR /f "tokens=1*delims=:" %%r IN ('findstr "Apple Banana Grapes" *.txt') do (
IF "!filename!"=="%%r" (
SET "line=!line!|%%s"
) ELSE (
IF DEFINED filename >>%resultfile% ECHO(!filename! !line!
SET "filename=%%r"
SET "line=%%s"
)
)
IF DEFINED filename >>%resultfile% ECHO(!filename! !line!
TYPE %resultfile%
popd
GOTO :EOF
I set up the destination filename as a variable in order to avoid the problem that the results.txt file may be included in the input processing, since it is created in the same directory as the data files.
I also changed the directory name to suit my system.
#echo off
setlocal EnableDelayedExpansion
cd D:\Source
set "filename="
for /F "tokens=1* delims=:" %%a in (
'findstr "Apple Banana Grapes" *.txt') do (
if not defined filename (
set /P "=%%a %%b" < NUL
set "filename=%%a"
) else if "!filename!" equ "%%a" (
set /P "=|%%b"
) else (
echo/
set /P "=%%a %%b" < NUL
set "filename=%%a"
)
)
echo/
Some notes on previous code:
endlocal command at end is not necessary.
pushd command and a popd at end may be replaced by setlocal followed by cd at beginning and nothing at end.
In findstr command you may define several strings to search separating they with space.

Compare file line count with a file content in all sub directories using batch file

I can compare the count of lines in a file with content of another file
for example:
file1 line count is 10
file2 contains 12
then not equal
using the following script
#ECHO off
rem using linecount and putfileinvar to compare count and datafile
Set _File=testfile.txt
Set /a _Lines=0
For /f %%j in ('Type %_File%^|Find "" /v /c') Do Set /a _Lines=%%j
set /p myvar= < filecount.tmp
rem echo %myvar%%_lines%
IF %myvar% == %_lines% (ECHO eq ) ELSE (ECHO neq )
Now I want do do this for a whole directory and its sub directories where every sub directory contains two files
datafile and its count in a sperate file
I want to compare the number of lines of the datafile with the count file
:: list foleders in the root directory and store them in list file
dir /b /o:n /ad > dirlist.txt
:: for each directory in list
FOR /F "tokens=*" %%v in (dirlist.txt) do (
::store dat file names in each directory in a temp file
::Log inside each folder
cd %%v
::list dat files in file.txt
dir *.dat /b /o:n > file.txt
::for each file stored in file.txt
FOR /F "tokens=*" %%m in (file.txt) do (
::count lines inside dat file
findstr /R /N "^" %%m | find /C ":" > save_temp_count.txt
::Get the contents of the temp file and save it to the %mycount% variable
set /a mycount<=save_temp_count.txt
)
::delete temp files
del file.txt
::Get all files tmp files
dir *.tmp /b /o:n > file.txt
::get file names in file.txt
for /F "tokens=*" %%j in (file.txt) do (
set /a fcount=<%%j
)
if %fcount% == %mycount% (echo 1eq ) else (echo neq & echo %%v >> ../result.txt)
::delete temp files
del file.txt
del save_temp_count.txt
::go up back to parent folder
cd ..
)
copy this and paste it in the root directory where your folders exist , note that this script will not handle unexpected scenarioes , like:
found more than 2 files in a folder.
extensions are different from expected ( dat , tmp ).
tmp files dont contain an integer.
hope this helps.

Batch file move specific files

I have a very large number of files with this template:
example1.part001.rar
example1.part002.rar
example1.part003.rar
...
example2.part001.rar
example2.part002.rar
example2.part003.rar
...
and sometimes with only two digits after "part"
example3.part01.rar
example3.part02.rar
example3.part03.rar
...
I'm trying to create a batch file that first makes n directories (n is for number of groups of files) with the name " example n ", and then that moves all relatives file into them.
I will explain better.
I have
cat.part01.rar
cat.part02.rar
cat.part03.rar
dog.part001.rar
dog.part002.rar
mouse.part01.rar
mouse.part02.rar
mouse.part03.rar
mouse.part04.rar
I want to first make the directories "cat", "dog" and "mouse, and then move all relatives file into them (I mean all "foldername.part*.rar in "foldername"), so "cat.part*.rar" files into "cat" folder and so on.
Files are many, and filenames are very very different and random.
Can somebody help me? Thanks
EDIT :
#echo off&cls
setlocal EnableDelayedExpansion
for %%a in (*.rar) do (set $file=%%~na
set $file=!$file:^.= !
call:work %%a)
exit /b
:work
for %%b in (!$file!) do (if not exist %%b md %%b
copy "%1" ".\%%b"
exit /b)
This should do it also, and handle filenames with ! in them too.
#echo off
for %%a in (*.rar) do (
if exist "%%a" for %%b in ("%%~na") do (
md "%%~nb" 2>nul
move "%%~nb.part*.rar" "%%~nb" >nul
)
)
pause
Here I get a list of groups by splitting the file name by '.'. I then get the uniq values of the first column. For each of the results I create the directory. Then move all files into the directory
#/usr/bin/sh
groupnames=(`ls *.rar | awk -F"." '{print $1}' | uniq`)
for i in ${groupnames[*]}; do
mkdir $i
mv $i.*.rar ./$i/
done
Example files of test:
ball.part1.rar
ball.part2.rar
cat.part01.rar
cat.part02.rar
dog.part001.rar
dog.part002.rar
The script creates folders ball, cat, dog, after that, it moves the files to their respective folders, works with partX, partXY and partXYZ in filename
#echo off
#break off
#title Batch file move specific files
#color 0a
#cls
setlocal EnableDelayedExpansion
if "%~1" NEQ "" (
set "WORKINGDIR=%~1"
) else (
set "WORKINGDIR=!CD!"
)
if not exist "!WORKINGDIR!\*.rar" (
set "WORKINGDIR=!CD!"
)
if not exist "!WORKINGDIR!\*.rar" (
echo There are no winrar files in this directory
echo.
echo Exiting...
echo.
ping -n 4 localhost>nul
pause
exit
)
for %%a in ( "!WORKINGDIR!\*.rar" ) do (
set "name=%%~nxa"
if "!name:~-4!" EQU ".rar" (
set "name=!name:~0,-4!"
)
if "!name:~-8,5!" EQU ".part" (
echo !name:~-7! | find ".">nul
if "!errorlevel!" NEQ "0" (
set "name=!name:~0,-8!"
) else (
set "skip=yes"
)
) else if "!name:~-7,5!" EQU ".part" (
echo !name:~-6! | find ".">nul
if "!errorlevel!" NEQ "0" (
set "name=!name:~0,-7!"
) else (
set "skip=yes"
)
) else if "!name:~-6,5!" EQU ".part" (
echo !name:~-5! | find ".">nul
if "!errorlevel!" NEQ "0" (
set "name=!name:~0,-6!"
) else (
set "skip=yes"
)
)
if not defined skip (
set "skip=no"
)
if "!skip!" EQU "no" (
if not exist "!WORKINGDIR!\!name!\" (
mkdir "!WORKINGDIR!\!name!\"
)
move /y "!WORKINGDIR!\%%~nxa" "!WORKINGDIR!\!name!\%%~nxa"
)
set "skip=no"
)
pause
exit

Resources