简体   繁体   中英

How to recursively delete all folders of a folder tree unless they contain a file with certain file extension?

How to go though a directory tree and delete all directories unless they contain a file with a particular file extension?

I tried Robocopy thinking the folders were empty. But all the folders have hidden files. So I need something that will take every folder in a directory that does not have a .pdf for example in it and delete it.

The task is to delete all directories/folders not containing a PDF file and also not containing a subdirectory/subfolder containing a PDF file. Let us look on an example to better understand the directory/folder deletion task.

The directory C:\Temp contains following subfolders and files:

  • Folder 1
    • Subfolder A
      • File 1A.txt
    • Subfolder B
      • File 1B.txt
    • Subfolder C
      • File 1C.pdf
    • File 1.cmd
  • Folder 2
    • Subfolder A
    • Subfolder B
      • File 2B.pdf
    • Subfolder C
      • File 2C.pdf
    • File 2.jpg
  • Folder 3
    • Subfolder A
      • File 3A.log
    • Subfolder B
    • File 3.doc
  • Last Folder & End
    • Subfolder A
      • Last File A.xls
    • Subfolder B
    • Subfolder C
      • Last File C.pdf

A folder is formatted bold. A hidden folder is formatted bold and italic. A hidden file is formatted italic.

The wanted folders and files after running the batch file should be:

  • Folder 1
    • Subfolder C
      • File 1C.pdf
    • File 1.cmd
  • Folder 2
    • Subfolder B
      • File 2B.pdf
    • Subfolder C
      • File 2C.pdf
    • File 2.jpg
  • Last Folder & End
    • Subfolder C
      • Last File C.pdf

This result can be achieved by executing following batch file:

@echo off
goto MainCode

:ProcessFolder
for /F "delims=" %%I in ('dir "%~1" /AD /B 2^>nul') do call :ProcessFolder "%~1\%%I"
if exist "%~1\*.pdf" goto :EOF
for /F "delims=" %%I in ('dir "%~1" /AD /B 2^>nul') do goto :EOF
if /I "%~1\" == "%BatchFilePath%" goto :EOF
rd /Q /S "%~1"
goto :EOF

:MainCode
setlocal EnableExtensions DisableDelayedExpansion
set "BatchFilePath=%~dp0"
if exist "C:\Temp\" cd /D "C:\Temp" & call :ProcessFolder "C:\Temp"
endlocal

Doing something recursively on a directory tree requires having a subroutine/function/procedure which calls itself recursively. In the batch file above this is ProcessFolder .

Please read the answer on Where does GOTO :EOF return to? The command goto :EOF is used here to exit the subroutine ProcessFolder and works only as wanted with enabled command extensions. FOR and CALL as used here require also enabled command extensions.

The main code of the batch file first enables explicitly the command extensions required for this batch file and disables delayed environment variable expansion to process correct also folders with an exclamation mark in name. This is the default environment on Windows, but it is better here to explicitly set this environment because the batch file contains the command RD with the options /Q /S which can be really very harmful on execution from within wrong environment or directory.

The subroutine ProcessFolder is not at end of the batch file as usual with a goto :EOF above to avoid an unwanted fall through to the command lines of the subroutine after finishing the entire task. For safety reasons the subroutine is in the middle of the batch file. So if a user tries to execute the batch file on Windows 95/98 with no support for command extensions nothing bad happens because first goto MainCode is executed successfully as expected, but SETLOCAL command line, calling the subroutine and last also ENDLOCAL fail and so no directory was deleted by this batch file designed for Windows with cmd.exe as Windows command processor instead of command.com .

The main code sets also current directory to the directory to process. So C:\Temp itself is never deleted by this code because of Windows prevents the deletion of a directory which is the current directory of any running process or contains a file opened by a running process with file access permission set to prevent other processes to delete the file while being opened by the process.

Next is called subroutine ProcessFolder with argument C:\Temp to process this folder recursively.

Last the initial environment is restored which includes also initial current directory on starting the batch file if this directory still exists.

The command for /D is usually used to do something on all subdirectories of a directory. But this is not possible here because FOR always ignores directories and files with hidden attribute set. For that reason it is necessary to use command DIR to get a list of all subdirectories in current directory including directories with hidden attribute set.

The command line dir "%~1" /AD /B 2>nul is executed by FOR in a separate command process started with cmd.exe /C in background. This is one reason why this batch file is quite slow. The other reason is calling the subroutine again and again which cause internally in cmd.exe to save and restore environment again and again.

Please read the Microsoft article about Using Command Redirection Operators for an explanation of 2>nul . The redirection operator > 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 using a separate command process started in background.

For each subdirectory in a directory the subroutine ProcessFolder calls itself. The first FOR loop in the subroutine is left if a directory does not contain one more subdirectory.

Then the subroutine checks in current directory if there is at least one *.pdf file. The IF condition used here is true even if the directory contains only a hidden PDF file. In this case the subroutine is exited without doing anything as this directory contains definitely a PDF file and therefore must be kept according to the requirements of the folder deletion task.

Next is checked if the current directory still contains at least one subdirectory as in this case the current directory must be also kept as one of its subdirectories contains at least one PDF file.

Last the subroutine checks if the current directory contains by chance the batch file as this directory must be also kept to finish the processing of the batch file.

Otherwise the current directory is deleted with all files on not containing a PDF file and no subdirectories and also not the currently running batch file as long as Windows does not prevent the deletion of the directory because of missing permissions or a sharing access violation.

Please note that the batch file does not delete other files in a directory which is not deleted as it can be seen also on the example.

For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.

  • call /?
  • cd /?
  • dir /?
  • echo /?
  • endlocal /?
  • for /?
  • goto /?
  • if /?
  • rd /?
  • setlocal /?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM