1

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:

  • Bookmarks.xml ---- to delete
  • DownloadMeta.xml ---- to delete
  • logfile.log ---- to delete
  • 1745388844.idx ---- to delete
  • TS1.c.pickle ---- to delete
  • TS1.prm.bak ---- to delete
  • !clear.bat ---- keep
  • .gitignore ---- keep
  • BookFlight.c ---- keep
  • CheckItinerary.c ---- keep
  • combined_TS1.c ----keep
  • pre_cci.c ---- keep
  • TS1.prm ---- keep
  • TS1.usr ---- keep
  • vuser_end.c ---- keep
  • vuser_init.c ---- keep
  • globals.h ---- keep
  • ScriptUploadMetadata.xml ---- keep

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

0

3 Answers 3

2

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)

  • just the names of files because of option /A-D (attribute not directory)
  • matching the default wildcard pattern * (any file name)
  • found in specified directory C:\Temp
  • in bare format because of option /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

  • case-insensitive because of option /I
  • and literally because of option /L
  • for lines which completely match because of option /X
  • one of the search strings specified with the options /C:
  • and outputs to handle STDOUT of background command process the inverted result because of option /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 /?
Sign up to request clarification or add additional context in comments.

Comments

0

Based upon the information you've provided, and that which is available inside .gitignore, I would suggest you use an ignore list, adding a few of your own.

I assume that !clear.bat is the file you're seeking help with, so I'd offer this as its content.

@CD /D "%~dp0"
@For /F "EOL=? Delims=" %%G In ('Dir /B /S /A:D') Do @RD /S /Q "%%G"
@(Del /A /F /Q *.bak *.c.pickle *.ci *.dat *.db *.idx *.sdf combined_*.c ^
 Breakpoints.xml CompilerLogMetadata.xml logfile.log mdrv.log mdrv_cmd.txt ^
 options.txt output.txt pre_cci.c ReplaySummaryReport.xml ThumbnailsCache.tmp ^
 UserTasks.xml)

You'll note, as previously mentioned, that whilst you're wanting to keep .c files, both combined_*.c and pre_cci.c are created during compilation and not required. If you wish to keep them, please remove them from lines 3 and 5 as necessary.

7 Comments

Failed: didn't remove "some_file.txt"
@AndrewKozyrev, that file definitely doesn't exist in your current file listing image, and most certainly didn't in your previous image either. I specifically mentioned it was based upon the ignore list, adding a few of your own. I then used the list provided in your linked image, to add a few of your own for you. I cannot have been expected to know which files existed, outside of the information you provided! Just add *.txt to the list!
Your solution is not filtering files, it iterates through file names, hardcoded, to delete, not file names to ignore. But thanks a lot, I appreciate it!
I know, that's what I told you it did! Only an absolute fool would create and post a script which permanently deletes all files like that. This method deletes only those which are known not to be required, because they're listed in .gitignore, or because you've specifically mentiond them in your question or its accompanying image!
I wrote .gitignore with ! to list the files to keep. It does not list the files to ignore, rather to keep.
|
0

The help of this command may be put you on the right direction findstr /?

/G:StringsFile Get search string from a file (/ stands for console).

You need to put all your strings into a file and use this syntax :

findstr /G:"Filter_File.txt"

/V Print only lines that do NOT contain a match.

/I Case-insensitive search.

So you can write something like that :

@echo off
Title Batch script delete files when file name does not match list of patterns
Set "Files2Keep=%~dp0Files2Keep.txt"

>"%Files2Keep%" (
    echo    !clear.bat
    echo    .gitignore
    echo    BookFlight.c
    echo    CheckItinerary.c
    echo    combined_TS1.c
    echo    pre_cci.c
    echo    TS1.prm
    echo    TS1.usr
    echo    vuser_end.c
    echo    vuser_init.c
    echo    globals.h
    echo    ScriptUploadMetadata.xml
)

@for /f "delims=" %%a in ('dir /b /a:-d ^|findstr /I /V /G:"%Files2Keep%"') do ( 
    If "%%~nxa" NEQ "%~nx0" (
        IF "%%~dpnxa" NEQ "%Files2Keep%" (
            Echo DEL /s /q "%%a"
        )
    )
)
pause

4 Comments

This deletes everything, icluding Files2Keep.txt file
This fails, because every file is deleted, nothing is kept.
@AndrewKozyrev I edited the answer to keep the file Files2Keep.txt not to be deleted !
This is the result: DEL /s /q ".gitignore" ... It still deletes everything.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.