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="
Related
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
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
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.
i have a directory in windows server in which several directories are there which i have sorted while listing. Now i need to find first 2 directories from that list.
can anyone please help me with DOS command?
here is the code you wanted
change the Directory path according to your requirement:
#echo off
setLocal EnableDelayedExpansion
c:
cd c:\
set /a count=0
for /f %%A in ('DIR /A:D /B') do (
set /a count+=1
if !count! LEQ 2 (
echo !count!.Directory name %%A
)
)
Output of above script tested output :
c:>first_twofiles.bat
1.dir name $Recycle.Bin
2.dir name Automation_Framework
Without looping:
cd /d "x:\source\path"
for /f "delims=[] tokens=1,2*" %%i in ('dir /b/ad ^| find /N /V ""') do #if %%i LEQ 2 echo %%j
The ordinal is available via %%i if needed. Note that the dir /b gets rid of the '.' and '..' entries and junctions or other links.
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%"