Exclude multiple folders with Dir command - batch-file

I had search thru the forum with excluding multiple files while using DIR command. But didn't find what i really needed. Some are even with PHP or VBS, really don't know how they works.
What I'm trying to do is *DIR*ing all profile folders and also excluding certain default folders, this is a part of showing what and how many users are having profiles on that computer.
I will explain a bit more because i may not fully be understood what my needs are.
If i use the DIR without findstr.
DIR /A:d /B "F:\Documents and Settings"
Output:
Administrator
All Users
Default User
LocalService
userprofile1
NetworkService
userprofile2
...
userprofileN
But my actual needs are:
userprofile1
userprofile2
...
userprofileN
I also got this far with my script now.
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
IF ERRORLEVEL 1 ECHO Your OS does not support enable extensions
DIR /A:d /B "F:\Documents and Settings" | findstr /v "Admin" | findstr /v "Default" | findstr /v "LocalService" | findstr /v "NetworkService"
EXIT
My above script actually works but is fixed and may not be pretty coded.
I would ask about is it possible to use a For loop to shorten the long findstr pipes and set a variable that contains the folder names to exclude ?
I prefer to use a variable instead of a text files that contains folders to exclude.
I came up with below but it duplicates the ouput:
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
IF ERRORLEVEL 1 ECHO Your OS does not support enable extensions
SET xUser="Admin" "Default" "hi_I_will_be_future_added"
FOR %%A IN (!Xuser!) DO (
DIR /A:d /B "F:\Documents and Settings" | findstr /v %%A
)
Thank you to this great forum and for all that may had helped both me and others.

#echo off
setlocal EnableDelayedExpansion
set exclude=/Administrator/All Users/Default User/LocalService/NetworkService/
for /F "delims=" %%a in ('DIR /A:d /B "F:\Documents and Settings"') do (
if "!exclude:/%%~Na/=!" equ "%exclude%" echo %%a
)
If you want to show the user name only (with no "F:\Documents and Settings" path), use echo %%~Na

Splitted in several lines for better reading, but, of course, it can be in a single line
#echo off
dir /ad /b "c:\Documents And Settings" ^
| findstr /l /i /x /v ^
/c:"Administrator" ^
/c:"All Users" ^
/c:"Default User" ^
/c:"LocalService" ^
/c:"NetworkService"
Or, instead of passing all the strings as /c:"..." arguments, you can generate a file with all the strings to exclude and use the /g:filename switch of findstr

F:\>dir /AD /B "c:\documents and settings"| FINDSTR /V "All Default Local Networ
k"
Admin
Administrator
F:\>

Related

Delete file with specific extension in batch file

I would like to recursively delete all files with a specific extension in a batch file.
I am aware of the following command:
del /s *.ext
However, this does on Windows also delete files with other extensions like e.g. .ext1 or .ext2 . The reason for this seems to be that the 8.3 file name of such a file ends with .ext and therefore also the files with longer extensions are matched.
I am looking for a replacement to the command above that recursively deletes all files with .ext extension but keeps files with longer extensions.
the where command works a bit differently (in regards to wildcards and short-names). Put a for /f loop around, and you're done. Your example would then translate to:
for /f "delims=" %%a in ('where /r . *.ext') do ECHO del "%%a"
Note: I disarmed the del command by just echoing it. Remove the ECHO after troubleshooting, when you are sure it does exactly what you want.
This also uses where.exe, but takes account of an issue not mentioned in another answer.
The issue is that where searches append each extension listed under %PATHEXT% to your .ext glob/spec. So whilst it will delete your target files, excluding files like .ext1 and .ext2 etc. it will now include for example, *.ext.com, *.ext.exe, *.ext.bat, *.ext.cmd, *.ext.vbs, *.ext.vbe, *.ext.js, *.ext.jse, *.ext.wsf, *.ext.wsh, and *.ext.msc etc.
The fix is to simply empty the content of %PATHEXT% before issuing the command. The following method does so within the For loop parenthsized command. As that is ran in another cmd.exe instance, it will not affect the instance in which the rest of your script resides:
#For /F "Delims=" %%G In ('"(Set PATHEXT=) & "%__APPDIR__%where.exe" /F /R "C:\SourceDir" "*.ext" 2>NUL"') Do #Del /A /F %%G
Obviously, you would modify, C:\SourceDir to contain the root location you require. The other current answers, use the current directory. If you want that, change it to ., or if you want the directory base as that of your batch file, change it to %~dp0.. Please do not remove any doublequotes.
Here are some alternative method examples, (please remember to adjust the drive/path/extension as needed)
If you wish to stick with the more traditional Dir command, then you could pipe the results through the findstr.exe utility, to exclude those matching the 8.3 names:
#For /F "Delims=" %%G In ('"Dir /B /S /A:-D "C:\SourceDir\*.ext" 2> NUL | "%__APPDIR__%findstr.exe" /I /L /E ".ext""') Do #Del /A /F "%%G"
You could also use the forfiles.exe utility for the task:
#"%__APPDIR__%forfiles.exe" /P "C:\SourceDir" /S /M "*.ext" /C "\"%__APPDIR__%cmd.exe\" /C \"If #IsDir==FALSE Del /A /F #File\""
Or this excruciatingly slow WMIC.exe utility method:
#"%__APPDIR__%wbem\WMIC.exe" DataFile Where "Drive='C:' And Path Like '\\SourceDir\\%%' And Extension='ext'" Delete 1> NUL 2>&1
Stephans answer is the shorter version, but you can use findstr's regex as well to match that the end of the name should be .ext
for /f "delims=" %%i in ('dir /b /s ^| findstr /IRC:"\.ext$"') do echo del "%%~i"

How can I loop through Windows Services and compare them with an text file in batch

I did a batch code which is a security check, to see if any system services have been modified.
This works through a previously registered text file, which contains the name of each Windows service.
AJRouter
ALG
AppIDSvc
Appinfo
AppReadiness
AppXSvc
AudioEndpointBuilder
Audiosrv
autotimesvc
AxInstSV
BDESVC
BFE
BITS
...
I managed to do the part where the code loops on each line of the text file, and checks if any Windows services are missing.
#echo off
for /F "tokens=*" %%A in (WindowsServices.txt) do (
SC QUERY %%A > NUL
IF ERRORLEVEL 1060 (ECHO %%A IS MISSING)
)
PAUSE
I would also like my code to check if there is any new service that is not registered in the text file. After a few attempts, I couldn't find a way to make my idea work. How can I do this?
#echo off
( for /f "tokens=1,*" %%A in (
'sc query type^= service type^= userservice state^= all ^| find "SERVICE_NAME:"'
) do #echo %%B
) > all.tmp
( for /f "tokens=*" %%A in (
'findstr /b /e /i /l /v /g:"WindowsServices.txt" "all.tmp"'
) do #echo + %%A
for /f "tokens=*" %%A in (
'findstr /b /e /i /l /v /g:"all.tmp" "WindowsServices.txt"'
) do #echo - %%A
for /f "tokens=*" %%A in (
'findstr /b /e /i /l /g:"all.tmp" "WindowsServices.txt"'
) do #echo %%A
) > report.txt
del all.tmp
sort /+3 report.txt /o report.txt
type report.txt
Using an output format that maybe easier to read and easier to process with a script if you want to further processing with the output.
Output interpret as:
If leads with +, needs adding to WindowsServices.txt i.e. New.
If leads with -, is in WindowsServices.txt though not in registry i.e. Missing.
If leads with space, is in WindowsServices.txt and in registry i.e. Good.
If the last item listed is not wanted i.e. Good, then remove the last for loop. I added it for completeness so that all service names are accounted for.
findstr uses:
/b Matches pattern if at the beginning of a line.
/e Matches pattern if at the end of a line.
/i Specifies that the search is not to be case-sensitive.
/l Uses search strings literally.
/g Get search strings from the specified file.
sort gets all the service names in alphabetical order.
Note: Earlier Windows OSes may not have a userservice type for sc.exe, such as Windows 7. The code works on Windows 10 without modification.

Batch count all files but exclude those in a specific folder

So I'm going to count files in a directory including all subfolders and get a output as a number of how many files it found within the directory. The problem is I want to exclude all the folders that has the name error. Those files within that folder I do not want to be counted.
Simply...
for /r "\\server\share\folderA" %%G in (*.*) do (
set /A count=count + 1
)
echo %count%
Under folderA there are plenty of subfolders that I'm counting, but also the "error" folders that I do not want to count.
So I'm trying the following...
Create a temp file called exclude.txt and type error to that file
if not exist "c:\temp" mkdir "c:\temp" 2>nul
if not exist c:\temp\exclude mkdir c:\temp\exclude 2>nul
echo error> %excludefolder%\exclude.txt
Now I want to combine this somehow. Basically do something like this...
for /r "\\server\share\folderA" %%G in (*.*) EXCLUDE: c:\temp\exclude\exclude.txt do (
set /A count=count + 1
)
But I'm aware this will not work and I'm not sure how to work it out. Does anyone know? Thanks!
Use DIR /S /B /A-D to iterate all files. The output includes the full path to each file.
Pipe that result to FINDSTR /L /I /V "\\error\\ to filter out paths that contain \error\. This will also exclude any folders within an error folder. The search could be modified to exclude only 'error' but include children of 'error'.
Pipe that result to FIND /C /V "" to count the number of files (lines).
dir /s /b /a-d | findstr /liv "\\error\\" | find /c /v ""
The above will simply display the count.
If you want to capture the count in a variable, then use FOR /F to parse the output of the above command. Unquoted poison characters like | must be escaped when used in FOR /F.
#echo off
for /f %%N in ('dir /s /b /a-d^|findstr /liv "\\error\\"^|find /c /v ""') do set count=%%N
echo count=%count%
You can exclude from count the folder containing the string "error" :
#echo off
set count=0
for /r "\\server\share\folderA" %%a in (*.*) do (
echo %%~pa | find /i "error" || set /A count+=1
)
echo %count%
It's a good way if you sure that you just have ONE Error folder. If you have another folder containing the string "error" it will be excluded too from count.

findstr for filename in win7 batch file

I'm kind of struggling with the following search.
I need to look for files which are misplaced in wrong folders. I have the following testing structure (in reality it is hudreds of folders):
C:\test2\John\John_phone.txt
C:\test2\Mary\John_address.txt
C:\test2\Mary\Mary_address.txt
C:\test2\Mary\Mary_phone.txt
C:\test2\Mary\Peter_address.txt
The files John_address.txt and Peter_address.txt are misplaced in Mary's folder. I want to check Mary's folder for any misplaced files and list them in a separate log file. So for the example above the log would contain the names (paths) of the two misplaced files, The deciding identifier is the person's name. I have this piece of code:
#echo off
cls
set /p name="Specify the name: "
::forfiles /p "%CD%\%name%" /s /m *.* /c "cmd /c echo #path">>log.txt
forfiles /p "%CD%\%name%" /s /m "| findstr /i /v "\*%name%*"" /c "cmd /c echo #path">>log.txt
pause
The commented line for forfiles works (lists all files in the folder), so I have an issue with findstr: ERROR: Files of type "| findstr /i /v *Mary*" not found.
The /v switch with findstr should find all files that do not contain the specified name, but obviously I'm doing something wrong while using it as input for forfiles.
I don't want to use the dir command since it lists additional information and I need to integrate the output into larger log file (I need to get only the path of the misplaced file).
Any help is appreciated.
Thanks.
Edit: Would it be easier to write the code if the correct file name would be fixed like this?
All_data_%NAME%_new.txt
The stuff before and after the name would be fixed and this format of the file name would be the only correct option, so anything else would have to be reported.
For a simple solution
#echo off
setlocal enableextensions disabledelayedexpansion
set "rootFolder=c:\test2"
( for /d %%z in ("%rootFolder%\*"
) do for %%y in ("%%~fz\*"
) do for /f "tokens=1 delims=_" %%a in ("%%~ny"
) do if /i not "%%~nxz"=="%%a" echo %%~fy
) > log.txt
This will iterate the files under each of the folders testing if their name starts with the same string that the folder name.
edited the original proposed solution does not work as intended, so, removed
edited - as the name of the file has not a fixed format, and the name of the folder can be in any place, this can be used
#echo off
setlocal enableextensions disabledelayedexpansion
set "rootFolder=c:\test2"
rem create a temporary file to hold the patterns to match against the list
rem of files to determine if it is correctly placed
set "patterns=%temp%\%~nx0.%random%.tmp"
> "%patterns%" (
for /d %%a in ("%rootFolder%\*") do echo(\\%%~nxa\\[^^\\]*%%~nxa[^^\\]*
)
rem Get the list of files, and filter to only get those that do not match
rem the generated patterns
dir /s /b /a-d "%rootFolder%\*" ^
| findstr /r /i /c:"%rootFolder:\=\\%\\[^\\]*\\." ^
| findstr /r /i /e /v /g:"%patterns%" ^
> log.txt
rem Patterns file is no longer needed
del "%patterns%" >nul 2>nul
this should help provided that comparison is case sensitive
for /f "delims=.'_\ tokens=2,3,*" %%a in ('forfiles /s /m *.txt /c "cmd /c echo #relpath"') do if NOT "%%a"=="%%b" #echo "%%a\%%b_%%c

batch file - counting number of files in folder and storing in a variable

I am very new to this. Please help me
I was trying to write a batch file program to count number of files in a folder and assign that to a variable and display it to verify that it has been stored
please help me with the syntax,
thank you in advance
-VK
I'm going to assume you do not want to count hidden or system files.
There are many ways to do this. All of the methods that I will show involve some form of the FOR command. There are many variations of the FOR command that look almost the same, but they behave very differently. It can be confusing for a beginner.
You can get help by typing HELP FOR or FOR /? from the command line. But that help is a bit cryptic if you are not used to reading it.
1) The DIR command lists the number of files in the directory. You can pipe the results of DIR to FIND to get the relevant line and then use FOR /F to parse the desired value from the line. The problem with this technique is the string you search for has to change depending on the language used by the operating system.
#echo off
for /f %%A in ('dir ^| find "File(s)"') do set cnt=%%A
echo File count = %cnt%
2) You can use DIR /B /A-D-H-S to list the non-hidden/non-system files without other info, pipe the result to FIND to count the number of files, and use FOR /F to read the result.
#echo off
for /f %%A in ('dir /a-d-s-h /b ^| find /v /c ""') do set cnt=%%A
echo File count = %cnt%
3) You can use a simple FOR to enumerate all the files and SET /A to increment a counter for each file found.
#echo off
set cnt=0
for %%A in (*) do set /a cnt+=1
echo File count = %cnt%
#echo off
setlocal enableextensions
set count=0
for %%x in (*.txt) do set /a count+=1
echo %count%
endlocal
pause
This is the best.... your variable is: %count%
NOTE: you can change (*.txt) to any other file extension to count other files.....
The mugume david answer fails on an empty folder; Count is 1 instead of a 0 when looking for a pattern rather than all files. For example *.xml
This works for me:
attrib.exe /s ./*.xml | find /v "File not found - " | find /c /v ""
This might be a bit faster:
dir /A:-D /B *.* 2>nul | find /c /v ""
`/A:-D` - filters out only non directory items (files)
`/B` - prints only file names (no need a full path request)
`*.*` - can filters out specific file names (currently - all)
`2>nul` - suppresses all error lines output to does not count them
To build for statement you should know some details at first.
for /F %%i in ('dir /A:-D /B *.* 2^>nul ^| find /c /v ""') do set "COUNT=%%i"
The example above would work, but if you want to copy paste it into another for-expression - might not.
The for /F ... expression by default has ; character as EOL character and space+tabulation characters as line separators.
If you use a file path as input in for-expression, then you can override these characters:
for /F "eol= delims=" %%i in (";My file path") do echo.Value: %%i
Where the end of eol= might not visible here. It is just a file path invalid not printable character, in this case - code 04. In most consoles and editors (except stackoverflow itself) you can type it as:
press ALT
type 04 from numeric keypad
release ALT
Another issue avoid here is always reset variable you want to use before the for-expression in case if for-expression is not executed:
set FILE=undefined
for /F %%i in (";My file path") do set "FILE=%%i"
echo.FILE=%FILE%
The fastest code for counting files with ANY attributes in folder %FOLDER% and its subfolders is the following. The code is for script in a command script (batch) file.
#for /f %%a in ('2^>nul dir "%FOLDER%" /a-d/b/-o/-p/s^|find /v /c ""') do set n=%%a
#echo Total files: %n%.
Change into the directory and;
attrib.exe /s ./*.* |find /c /v ""
EDIT
I presumed that would be simple to discover. use
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "batchfile.bat";
p.Start();
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
I run this and the variable output was holding this
D:\VSS\USSD V3.0\WTU.USSD\USSDConsole\bin\Debug>attrib.exe /s ./*.* | find /c /v "" 13
where 13 is the file count. It should solve the issue
for /F "tokens=1" %a in ('dir ^| findstr "File(s)"') do echo %a
Result:
C:\MyDir> for /F "tokens=1" %a in ('dir ^| findstr "File(s)"') do #set FILE_COUNT=%a
C:\MyDir> echo %FILE_COUNT%
4 // <== There's your answer
FOR /f "delims=" %%i IN ('attrib.exe ./*.* ^| find /v "File not found - " ^| find /c /v ""') DO SET myVar=%%i
ECHO %myVar%
This is based on the (much) earlier post that points out that the count would be wrong for an empty directory if you use DIR rather than attrib.exe.
For anyone else who got stuck on the syntax for putting the command in a FOR loop, enclose the command in single quotes (assuming it doesn't contain them) and escape pipes with ^.
I have used a temporary file to do this in the past, like this below.
DIR /B *.DAT | FIND.EXE /C /V "" > COUNT.TXT
FOR /F "tokens=1" %%f IN (COUNT.TXT) DO (
IF NOT %%f==6 SET _MSG=File count is %%f, and 6 were expected. & DEL COUNT.TXT & ECHO #### ERROR - FILE COUNT WAS %%f AND 6 WERE EXPECTED. #### >> %_LOGFILE% & GOTO SENDMAIL
)
With a for loop:
FOR /F %i IN ('dir /b /a-d "%cd%" ^| find /v /c "?"') DO set /a count=%i
echo %count%
Without/avoiding for loop:
(dir /b /a-d ^| find /v /c "?") | (set /p myVar=& cmd /c exit /b %myVar%)
set count=%errorlevel%
echo %count%
Tested in Win 10 cmd
Solution
Requires enabling Windows Subsystems For Linux
Ensure directoryToCount is set to the respective directory
SET directoryToCount=C:\Users\
dir %directoryToCount% > contentsOfDir.txt
echo cat contentsOfDir.txt ^| grep File > countFiles.sh
sh countFiles.sh
del countFiles.sh
del contentsOfDir.txt
Explanation
In both bash and batch environments, the output of a command can be redirected to a file using the > operator.
For example, echo hello world > myFile.txt will produce a file named myFile.txt with hello world as its text.
In a bash environment, one can cat the contents of a File and grep a particular line from the file containing a specified pattern.
For example, cat myFile.txt | grep hello will return lines containing hello
If Windows Subsystems for Linux is enabled, then one can execute sh from a Command Prompt to access a linux-like environment.
Therefore, we can solve this by doing the following
Use dir to acquire a list of files in the directory, as well as the number of files
Redirect the output of dir to a file (perhaps named contentsOfDir.txt).
Create a .sh file to grep for File from contentsOfDir.txt
Call the .sh file from command prompt to invoke the grep
Delete the .sh file
Delete contentsOfDir.txt

Resources