I want to delete all files in a directory except those whose name matches a certain pattern. A typical example of the kind of files in this directory is as follows:
i want to keep files with names in a list of patterns:
list_to_ignore = ["!clear.bat", ".gitignore", "*.usr", "default.cfg",
"default.usp", "*.c", "*lobals.h", "*custom_body.h",
"*body_variables.txt", "*loadMetadata.xml", "*.prm" ]
For example:
file TS2.c.pickle does not match any item in the list, because it ends with .pickle extension. It should be deleted.
file somefile.c matches "*.c" pattern, because it ends with .c. It should be kept.
file Metadata.xml does not match any pattern, because it lacks prefix "load" at the beginning. It should be deleted.
file Globals.h matches "lobals.h pattern. It should be kept.
Here is what I tried:
@echo off
FOR /d %%a in ("./*") DO rd "%%a" /q /s
FOR %%i in (*.*) DO ^
if not "%%i"=="!clear.bat" ^
if not "%%i"==".gitignore" ^
if not "%%i"=="*.usr" ^
if not "%%i"=="default.cfg" ^
if not "%%i"=="default.usp" ^
if not "%%i"=="*.c" ^
if not "%%i"=="*lobals.h" ^
if not "%%i"=="*custom_body.h" ^
if not "%%i"=="*body_variables.txt" ^
if not "%%i"=="*ploadMetadata.xml" ^
if not "%%i"=="*.prm" ^
DEL /s /q "%%i"
pause
Here is a list of all files in a local directory with check marks
Hope this makes sense. If this is not an appropriate question let me know.
Many thanks
This could be done with the following command line in the batch file:
@for /F "eol=| delims=" %%I in ('dir "%~dp0" /A-D /B 2^>nul ^| %SystemRoot%\System32\findstr.exe /I /L /X /V /C:"!clear.bat" /C:".gitignore" /C:"BookFlight.c" /C:"CheckItinerary.c" /C:"combined_TS1.c" /C:"pre_cci.c" /C:"TS1.prm" /C:"TS1.usr" /C:"vuser_end.c" /C:"vuser_init.c" /C:"globals.h" /C:"ScriptUploadMetadata.xml" /C:"%~nx0"') do @del /A /F "%~dp0%%I"
This command line results in starting one more command process in background with %ComSpec% /c
and the command line between '
appended as additional arguments. So executed is with Windows installed to C:\Windows
and full qualified file name of batch file being C:\Temp\Test.bat
:
C:\Windows\System32\cmd.exe /c dir "C:\Temp\" /A-D /B 2>nul | C:\Windows\System32\findstr.exe /I /L /X /V /C:"!clear.bat" /C:".gitignore" /C:"BookFlight.c" /C:"CheckItinerary.c" /C:"combined_TS1.c" /C:"pre_cci.c" /C:"TS1.prm" /C:"TS1.usr" /C:"vuser_end.c" /C:"vuser_init.c" /C:"globals.h" /C:"ScriptUploadMetadata.xml" /C:"Test.bat"
DIR outputs to handle STDOUT (standard output)
/A-D
(attribute not directory)*
(any file name)C:\Temp
/B
which means just file name and file extension.It is not really possible that command DIR outputs an error message in this case because of no directory entry found matching these criteria to handle STDERR (standard error) as there must be the batch file in this directory. But 2>nul
would redirect this error message to handle STDERR of the command process started in background to suppress it.
The output of DIR is redirected with |
to STDIN (standard input) of FINDSTR which searches
/I
/L
/X
/C:
/V
which means all lines NOT being completely ANY of the searched strings.Read also the Microsoft article about Using command redirection operators for an explanation of 2>nul
and |
. The redirection operators >
and |
must be escaped with caret character ^
on FOR command line to be interpreted as literal character when Windows command interpreter processes this command line before executing command FOR which executes the embedded dir
command line with findstr
with using a separate command process started in background.
FOR captures the output to handle STDOUT of background command process and processes this output line by line after started cmd.exe
terminated itself after finishing execution of the command line.
FOR skips all empty lines which do not occur here. FOR would next split up each line into substrings using the characters normal space and horizontal tab as string delimiters. A line would be ignored by FOR on first substring starting with ;
being the default end of line character. Otherwise just the first space/tab delimited string would be assigned to loop variable I
for further processing.
This line splitting behavior is not wanted here as file names can contain one or more spaces and can start with a semicolon after 0 or more leading spaces. For that reason option eol=|
is used to define vertical bar as end of line character which no file name can contain ever and option delims=
is used to define an empty list of string delimiters to turn off splitting the file names up into substrings.
Therefore each file name output by DIR not being one of the strings specified as search strings for FINDSTR is assigned completely to the loop variable I
and FOR executes the command DEL which deletes the file independent on being a hidden file because of using option /A
and even on being a read-only file because of option /F
.
The command line rewritten for using FINDSTR with regular expressions to filter out file names matching one of the search patterns:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "BatchFileName=%~nx0"
set "BatchFileName=%BatchFileName:.=\.%"
for /F "eol=| delims=" %%I in ('dir "%~dp0" /A-D /B 2^>nul ^| %SystemRoot%\System32\findstr.exe /I /R /X /V /C:"!clear\.bat" /C:"\.gitignore" /C:"^.*\.usr" /C:"default\.cfg" /C:"default\.usp" /C:"^.*\.c" /C:"^.*lobals\.h" /C:"^.*custom_body\.h" /C:"^.*body_variables\.txt" /C:"^.*ploadMetadata\.xml" /C:"^.*\.prm" /C:"%BatchFileName%"') do @del /A /F "%~dp0%%I"
endlocal
Note: FINDSTR option /R
is used instead of /L
for a regular expression search which requires .
being escaped with \
to be interpreted as literal character and *
being modified to ^.*
to match any character from beginning of line 0 or more times.
The same can be achieved with batch file name not containing a space character also by using:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "BatchFileName=%~nx0"
set "BatchFileName=%BatchFileName:.=\.%"
for /F "eol=| delims=" %%I in ('dir "%~dp0" /A-D /B 2^>nul ^| %SystemRoot%\System32\findstr.exe /I /R /X /V "!clear\.bat \.gitignore ^.*\.usr default\.cfg default\.usp ^.*\.c ^.*lobals\.h ^.*custom_body\.h ^.*body_variables\.txt ^.*ploadMetadata\.xml ^.*\.prm %BatchFileName%"') do @del /A /F "%~dp0%%I"
endlocal
FINDSTR interprets a space in a search string specified with just "..."
as OR expression while a space in a search string specified with /C:"..."
is interpreted literally as space character.
To understand the commands used and how they work, open a command prompt window, execute there the following commands, and read the displayed help pages for each command, entirely and carefully.
call /?
... explains %~dp0
... drive and path of argument 0 which is always the full path of the batch file currently executed by Windows command processor and ending always with a backslash and %~nx0
... file name with extension of the batch file.del /?
dir /?
endlocal /?
findstr /?
for /?
set /?
setlocal /?