Batch - Counting lines in files in current folder and subfolders - batch-file

This is my script, what it does is count lines from cpp, h, hpp, cs, c files in current folder.
What I want to do is count in subfolders also, but it seems I can't manage to do this.
I made some recursion tries, but I can't implement it in the current code.
call::CountLines Modules\Output\HTML.Tidy\
goto:eof
:CountLines
setlocal
set /a totalNumLines = 0
SETLOCAL ENABLEDELAYEDEXPANSION
for /r %%f in (%~1*.cpp %~1*.h %~1*.hpp %~1*.cs %~1*.c) do (
for /f %%C in ('Find /V /C "" ^< %%f') do set Count=%%C
set /a totalNumLines+=!Count!
)
echo Total number of cod lines for %~1: %totalNumLines% >> log.txt
Please let me know if you know a solution or a better way.
Regards,
Stefan

Path information must not be within IN() clause when using FOR /R. The root path should follow the /R option instead.
#echo off
:CountLines
setlocal
set /a totalNumLines = 0
for /r %1 %%F in (*.cpp *.h *.hpp *.cs *.c) do (
for /f %%N in ('find /v /c "" ^<"%%F"') do set /a totalNumLines+=%%N
)
echo Total number of code lines for %1 = %totalNumLines% >>log.txt
I don't remember the difference, but type file|find /c /v "" and find /c /v "" <file can give different results. I don't remember what the trigger condition is, or which is better.

Run this through your fingers:
#echo off
cd /d "%~1"
for /f "delims=" %%f in ('dir *.cpp *.h *.hpp *.cs *.c /b /s /a-d ^|find /c /v "" ') do set Count="%%f"
echo "%count%"

Related

BAT batch file to count files in a folder and then subtract 1

I have a BAT script that counts the number of files in a folder and exports the results into a .txt. It works great, but I'm in a situation where I need to subtract 1 from the value it's currently counting. How could I alter my script to do that?
#echo off
FOR /D %%G in ("*") DO (
PUSHD "%%G"
FOR /F "delims=" %%H in ('dir /a-d /b * ^|find /C /V ""') DO echo %%G %%H>>"..\count.txt"
POPD
)
Your goal is to use %%H with the SET /A command to do the Arithmetic. I chose to use %%G as part of the DIR command. This way you do not need PUSHD and POPD. I also chose to use an IF command to make sure the count is not zero so that it does not substract 1.
I moved the redirection of the output at the end because this opens the file for writing once instead of every time it writes a directory to the output.
The CALL command and the double percent symbols on the variable allows us to use the variable without having to enable delayed expansion.
#echo off
(FOR /D %%G in ("*") DO (
FOR /F "delims=" %%H in ('dir /a-d /b "%%G\*" 2^>NUL ^|find /C /V ""') DO (
IF NOT "%%H"=="0" SET /A "count=%%H-1"
CALL echo %%G %%count%%
)
))>count.txt

findstr on multipule values

Please forgive me if this is glaring obvious but I have the behaviour of this for loop, which loops through certain named directories (US_Site4 etc.) and reads a config file in each of them to run a command separately for each:
setlocal enabledelayedexpansion
REM The Root to start searching from
SET "InstallSets=D:\InstallSets"
REM Folders to not search with in
SET "ExcludeStr=findstr /I /v ^"\Master Files \Training \Software^""
REM
SET "InstallSets=D:\InstallSets"
for /f "delims=*" %%F IN ('dir /s /b /on "!InstallSets!" ^| findstr /E /C:"Config.xml" ^| !ExcludeStr!') do (
(ECHO "%%F"| findstr /I "\US_Site4 \US_Site5" 1>NUL) && (
ECHO "%%F"...
)
)
And I would like to be able replicated in a more user configurable way for furure additions, i.e. settings a variable at the top of a batch file, e.g.:
setlocal enabledelayedexpansion
REM The Root to start searching from
SET "InstallSets=D:\InstallSets"
REM Folders to not search with in
SET "ExcludeStr=findstr /I /v ^"\Master Files \Training \Software^""
REM Folders to search in only
SET "DoOnlyStr=findstr /I ^"\US_Site4 \US_Site5^" 1>NUL"
for /f "delims=*" %%F IN ('dir /s /b /on "!InstallSets!" ^| findstr /E /C:"Config.xml" ^| !ExcludeStr!') do (
(ECHO "%%F"| %DoOnlyStr%) && (
ECHO "%%F"...
)
)
The first one brings back 2 results which are site4 and 5 as expected, however the second one brings back 4 (The 2 I wanted but duplicated). Why is this and how could get a "user friendly" configurable version like just setting the variable? I want to then later make a second file with findstr /I /V to do the opposite and do everything else BUT Site4 and 5.
Kind regards
Adam
It was the 1>NUL that was displaying only the 1 output and when that was in a variable it wasn't behaving as it should, so it was displaying 2 (as it seemed to when I removed it also), But is was a combination of the comment from #aschipfl with removing the " " on the set variables and how I structured it below. So my final solution that worked for me was:
setlocal enabledelayedexpansion
REM The Root to start searching from
SET "InstallSets=D:\InstallSets"
REM Folders to not search with in
SET ExcludeStr=findstr /I /v ^"\Master Files \Training \Software^"
REM Folders to search in only
SET DoOnlyStr=findstr /I ^"\US_Site4 \US_Site5^"
for /f "delims=*" %%F IN ('dir /s /b /on "!InstallSets!" ^| findstr /E /C:"Config.xml" ^| !ExcludeStr!') do (
(ECHO "%%F"| %DoOnlyStr% 1>NUL) && (
ECHO "%%F"...
)
)
Unsure why the !DoOnlyStr! didn't work though and it had to be %DoOnlyStr% as I have setlocal enabledelayedexpansion at the start

Count folders with names ending )x

I have a batch file which totals the number of directories:
for /d %%a in (*) do set /a count+=1
Now I need to total the directory names ending with the string )x, e.g. Mona Lisa (1986)x
I have tried unsuccessfully with:
for /d %%a in (")x") do set /a count+=1
You can let the find command count the items filtered by the dir command:
dir /B /A:D "*)x" | find /C /V ""
Prepend or append 2> nul to the dir part to suppress error messages in case no such directories exist.
To capture the resulting value and store it in a variable, use a for /F loop:
for /F %%C in ('2^> nul dir /B /A:D "*)x" ^| find /C /V ""') do set "COUNT=%%C"
echo %COUNT%
for /d %%d in (*^)x) do set /a count+=1
You may first want to check that it finds them correctly:
for /d %%d in (*^)x) do echo "%%~d"
Just an alternative, (the difference being that this doesn't ignore some directories, such as hidden ones):
For /F %%A In ('Dir /AD "*)x" 2^>Nul') Do Set "count=%%A"
You should really precede this with Set "count="

Batch script to delete files in folder that does not contain certain word

I am new to batch scripting . I need to delete all files in a folder that DOES NOT contains some word in the file
found this code
#echo off
setlocal
pushd C:\Users\admin\Desktop\bat
findstr /ip /c:"importantWord" *.txt > results.txt
popd
endlocal
So how i can WHITE list this files, and delete all other?
Or i think there is easy way with just check if !contains and delete
but i don`t know how?
Supposedly, this problem could be solved in a very simple way combining these findstr switches: /V that show results when the search string is not found, and /M that show just the name of the files; that is:
#echo off
setlocal
cd C:\Users\admin\Desktop\bat
for /F "delims=" %%a in ('findstr /ipvm /c:"importantWord" *.txt') do del "%%a"
Unfortunately, the combination of /V and /M switches don't properly work: the result of /V is based on lines (not files), so a modification in the method is needed:
#echo off
setlocal
cd C:\Users\admin\Desktop\bat
rem Create an array with all files
for %%a in (*.txt) do set "file[%%a]=1"
rem Remove files to preserve from the array
for /F "delims=" %%a in ('findstr /ipm /c:"importantWord" *.txt') do set "file[%%a]="
rem Delete remaining files
for /F "tokens=2 delims=[]" %%a in ('set file[') do del "%%a"
This method is efficient, particularly with big files, because findstr command report just the name of the files and stop searching after the first string match.
#echo off
setlocal
set "targetdir=C:\Users\admin\Desktop\bat"
pushd %targetdir%
for /f "delims=" %%a in ('dir /b /a-d *.txt') do (
findstr /i /p /v /c:"importantWord" "%%a" >nul
if not errorlevel 1 echo del "%%a"
)
popd
endlocal
Not really sure what you want to do with /pfiles - files containing non-ansi characters appear to return errorlevel 1for these. if not errorlevel 1 will echo the files that do not contain the required string - remove the echo to actually delete the file(s)
This should work:
#ECHO OFF
SETLOCAL EnableDelayedExpansion
SET "pathToFolder=C:\FolderToEmpty"
SET "wordToSearch=ImportantWord"
FOR /F "tokens=*" %%F IN ('dir %pathToFolder% /b *.txt') DO (
findstr /IP %wordToSearch% "%pathToFolder%\%%F">nul
IF !ERRORLEVEL!==1 (
DEL /Q "%pathToFolder%\%%F"
)
)
You will have to set the proper path to the folder you want to delete the files from and to replace ImportantWord with the substring you are looking for.

Windows Command to identify folders with only one file

I need a command to run from the Windows CLI to identify any folders (or sub folders) that contain only one file. If the folder contains two files, it should not be included. In the end, I need to output this list to a text file. It should contain the full folder path.
Ex: OutputLog.txt
C:\fold1
C:\fold1\sub
C:\fold3
C:\fold4
This should work to identify folders with one file.
#echo off
for /d /r "d:\base\folder" %%a in (*) do (
dir /b /a-d "%%a" 2>nul |find /c /v "" |findstr "^1$" >nul && >>file.txt echo %%a
)
#echo off
setlocal EnableDelayedExpansion
(for /D /R %%a in (*) do (
set count=0
for %%b in ("%%a\*.*") do set /A count+=1
if !count! equ 1 echo %%a
)) > OutputLog.txt
#echo off
set "parentfolder=c:\test"
for /f "tokens=* delims=" %%F in ('dir /s /a:d /b "%parentfolder%"') do (
dir "%%F"|findstr /b "1 File(s)" >nul 2>&1 && echo %%F
)
This will list all subfolders with only one file in a parent folder .As it checks the string of the dir command output it should be altered if language settings/windows version provide different DIR command output.

Resources