Viki2016
Viki2016

Reputation: 55

Batch command to delete everything (sub folders and files) from a folder except one file

First of all, similar questions have been answered in past but not exactly the one I have. In some other solutions, hiding folders/files and changing attributes were suggested and I do not want this, unless there is no simpler way available. Also, I have tried the solution suggested here (and couple of others): MS-DOS command to delete all files except one.

But did not work for my need due to two reasons:

  1. This also deleted the file, I did not want to.
  2. This did not delete the sub-folders but only the files.

So, I have folder c:/users/data and in there, I have 5 folders and 6 files I want to delete everything except one which is web.config and to do that I run the batch file like this:

@echo off
for %%j in (C:\Users\data\*) do if not %%j == Web.config del %%j
pause

But when I run the batch file, this deletes all the files including web.config and also, does not delete any of the sub-folders and if I use the /d switch then it only deletes folders not files. How can I delete both files and folders?

Upvotes: 1

Views: 4096

Answers (3)

aschipfl
aschipfl

Reputation: 34909

Here is the way I would do it:

pushd "C:\Users\data" || exit /B 1
for /D %%D in ("*") do (
    rd /S /Q "%%~D"
)
for %%F in ("*") do (
    if /I not "%%~nxF"=="web.config" del "%%~F"
)
popd

The basic code is taken from my answer to the question Deleting Folder Contents but not the folder but with the del command replaced by a second for loop that walks through all files and deletes only those not named web.config.

Note that this approach does not touch the original parent directory, neither does it touch the original file web.config. The great advantage of this fact is that no attributes are going to be lost (for instance, creation date and owner).

Explanation

  • change to root directory by pushd; in case of failure, skip the rest of the script;
  • iterate through all the immediate sub-folders of the root by a for /D loop and delete them recursively by rd /S with all their contents;
  • iterate through the files located in the root by a standard for loop; use the ~nx modifier of the loop variable to expand base name (n) and extension (x) of each file, compare it with the given file name (if) in a case-insensitive manner (/I) and delete the file by del only in case it does not match (not);
  • restore former working directory by popd finally;

The main problems in your code are:

  • that you compare more that the pure file name with the prefedined name, so there is not going to be found any match.
  • you needed to use case-insensitive comparison, because Windows does not care about the case of file names for searching.
  • you did not put quotation marks around the comparison expressions, so you are likely going to receive syntax error messages, depending on what special characters occur in the file names.
  • that you are using the del command only which just deletes files; to remove directories, you needed to use rd also.

Upvotes: 3

Viki2016
Viki2016

Reputation: 55

I also managed to do it, very similar to @aschipfl

For /D %%k in (C:\Users\data) do (For /d %%m in ("%%k\*") do rmdir /s /q "%%m"
For %%m in ("%%k\*") do if not %%m == %%k\Web.config del /q "%%m")

Upvotes: 0

MC ND
MC ND

Reputation: 70923

I'm not sure where the web.config file is stored or if there is more than one, so ...

Only one web.config file

Just lock the file (redirect the file as input) and remove anything else

@echo off
    setlocal enableextensions disabledelayedexpansion

    pushd "c:\users\data" && >nul 2>nul (
        <"web.config" rmdir . /s /q
        popd
    )

The code will

  1. (pushd) Change to the target folder (we need to be sure this will remove information only from the intended place) setting it as the current active directory and locking it (we can not remove the current active directory). If the command can change to the folder then

  2. (rmdir) Redirect the web.config as input to the rmdir command. This will lock the file so it can not be deleted until the command ends. The rmdir . /s /q remove anything not locked inside (and below) the current active directory

  3. (popd) Cancel the pushd command restoring the previous active directory

Several web.config files in multiple folders

Following the approach (copy, clean, restore) pointed by @Dominique

@echo off
    setlocal enableextensions disabledelayedexpansion

    pushd "c:\users\data" && >nul 2>nul (
        for %%t in ("%temp%\%~n0_%random%%random%%random%.tmp") do (
            robocopy . "%%~ft" web.config /s
            robocopy "%%~ft" . /mir
            rmdir "%%~ft" /s /q
        ) 
        popd
    )

The code will

  1. (pushd) Change to the target folder (we need to be sure this will remove information only from the intended place). If the command can change to the folder then

  2. (for) Prepare a reference (a random name) to a temporary folder to use

  3. (robocopy) Copy only the web.config files (and their folder hierarchy) from the source folder to the temporary folder

  4. (robocopy) Mirror the temporary folder to the source folder. This will remove any file/folder not included in the temporary copy

  5. (rmdir) Remove the temporary folder

  6. (popd) Cancel the pushd command restoring the previous active directory

Once the web.config files are saved, as the files in the source will match those in the temporay folder, they will not be copied back with the second robocopy call, but any file/folder in source that is not present in the temporary folder will be removed to mirror the structure in the temporary folder.

Upvotes: 1

Related Questions