批处理-删除文件夹中除文本文件中列出的文件夹以外的所有文件夹 [英] Batch - delete all folders in a folder except those listed in a text file

查看:105
本文介绍了批处理-删除文件夹中除文本文件中列出的文件夹以外的所有文件夹的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目的是删除名称在文本文件中列出的那些文件夹之外的所有文件夹(及其子文件夹).

The aim is to delete all folders (and their sub-folders) except those folders whose names are listed in a text file.

文本文件为"F:\Documents\Batch\my folders.txt",内容为

ABC
DEF

要删除的文件夹在"F:\Documents\Batch\Practice folder"中.它具有以下文件夹:ABCDEFGHIJKL.

The folders to be deleted are in "F:\Documents\Batch\Practice folder". It has the following folders in it: ABC, DEF, GHI and JKL.

运行我的批处理文件后,仅应保留ABCDEF,而应删除所有其他文件夹(GHIJKL)

After running my batch file, only ABC and DEF should remain and all other folder (GHI, JKL) should be deleted

这是我尝试过的:

@echo off

set WORKDIR="F:\Documents\Batch\Practice folder"
set LISTFILES="F:\Documents\Batch\my folders.txt"

pushd %WORKDIR%
for /d  %%G in (*) do (
    for /f "tokens=* usebackq" %%H in (%LISTFILES%) do (
        if %%G==%%H rd /s /q "%%G"
    )
)
popd

请帮助我找到一种更有效和/或更短的方法.

Please help me find a more effective and/or shorter way to do this.

该代码将删除所有与LISTFILES中的名称匹配的文件夹.但是当我执行以下任何操作时:

EDIT 1: That code deletes all the folders that match the names in the LISTFILES. But when I do any of:

if not %%G==%%H rd /s /q "%%G"
if not [%%G]==[%%H] rd /s /q "%%G"
if not "%%G"=="%%H" rd /s /q "%%G"

带有或不带有/i(即if /i)的所有文件夹,无论如何都将被删除. 所以,我尝试了一下,就可以了

with or without /i (i.e. if /i), all folders are delete regardless. So, I tried this and it work

@echo off
setlocal enableDelayedExpansion

set WORKDIR="D:\IFX\services\4"
set LISTFILES="D:\IFX\services\files.txt"

set delete=

pushd %WORKDIR%
for /d  %%G in (*) do (
    set delete=1
    for /f "tokens=* usebackq" %%H in (%LISTFILES%) do (
        if /i %%G equ %%H set delete=0
    )
    if !delete!==1 rd /s /q %%G
)
popd

问题中发布的

推荐答案

for /d %%G in (*) do处理当前目录中的每个非隐藏子目录,从而循环变量G在每个循环中包含没有路径的子目录的名称.设置了隐藏属性的子目录将被 FOR 忽略.

for /d %%G in (*) do as posted in question processes each non hidden subdirectory in current directory whereby loop variable G contains on each loop run the name of a subdirectory without path. Subdirectories with hidden attribute set are ignored by FOR.

并且由于启用了延迟的环境变量扩展,因此所涉及的 FOR 循环不适用于包含一个或多个感叹号的目录名称. %%G会扩展为当前目录名称,并且当该名称包含!时,感叹号将被解释为环境变量名称的开头或结尾.因此,将两个感叹号之间的所有内容替换为环境变量的当前值,其名称为两个感叹号之间的字符串,或者更可能在该名称不存在任何环境变量的情况下不包含任何内容.从目录名称中删除了一个(剩余的)感叹号.在由于启用延迟扩展而导致的这种额外预处理之后,(剩余)目录名实际上由诸如 IF RD 之类的适当命令进一步处理,无法删除或删除操作的目录错误的目录.

And because of enabled delayed environment variable expansion the FOR loop in question does not work for directory names containing one or more exclamation marks. %%G is expanded to current directory name and when this name contains !, the exclamation mark is interpreted as begin or end of an environment variable name. So everything between two exclamation marks is replaced by current value of the environment variable with name being the string between the two exclamation marks, or more likely with nothing in case of no environment variable exists with that name. A single (remaining) exclamation mark is removed from the directory name. After this additional preprocessing caused by enabled delayed expansion, the (remaining) directory name is really processed further by the appropriate command like IF and RD fails to delete the manipulated directory or deletes the wrong directory.

用于此任务的批处理文件也适用于名称中带有一个或多个感叹号的隐藏子目录和目录.

A batch file for this task working also for hidden subdirectories and directories with one or more exclamation mark in name is:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "WORKDIR=F:\Documents\Batch\Practice folder"
set "LISTFILE=F:\Documents\Batch\my folders.txt"
for /F "eol=| delims=" %%I in ('dir "%WORKDIR%\*" /AD /B 2^>nul ^| %SystemRoot%\System32\findstr.exe /I /L /V /X /G:"%LISTFILE%"') do rd /Q /S "%WORKDIR%\%%I"
endlocal

此批处理文件也可以优化为一行.

This batch file can be optimized to a single line too.

@for /F "eol=| delims=" %%I in ('dir "F:\Documents\Batch\Practice folder\*" /AD /B 2^>nul ^| %SystemRoot%\System32\findstr.exe /I /L /V /X /G:"F:\Documents\Batch\my folders.txt"') do @rd /Q /S "F:\Documents\Batch\Practice folder\%%I"

dir "F:\Documents\Batch\Practice folder\*" /AD /B输出以处理 STDOUT ,因为/AD(属性目录)由于/B而以纯格式显示目录F:\Documents\Batch\Practice folder中子目录的列表,这意味着目录名没有路径.带有这些选项的 DIR 输出还有设置了隐藏属性的子目录.

dir "F:\Documents\Batch\Practice folder\*" /AD /B outputs to handle STDOUT because of /AD (attribute directory) the list of subdirectories in directory F:\Documents\Batch\Practice folder in bare format because of /B which means just directory name without path. DIR outputs with these options also subdirectories with hidden attribute set.

对于给定的示例,输出列表为:

For the given example the output list is:

ABC
DEF
GHI
JKL

DIR 如果在指定目录中找不到任何子目录或者指定目录根本不存在,则输出一条错误消息以处理 STDERR 找到指定的 file 而不是目录.通过使用2>nul将其重定向到设备 NUL ,可以消除此可能且具有误导性的错误消息.

DIR outputs an error message to handle STDERR if it can't find any subdirectory in specified directory or the specified directory does not exist at all that it can't find the specified file instead of directory. This possible and misleading error message is suppressed by redirecting it with 2>nul to device NUL.

通过|重定向 DIR 输出到 STDOUT 的子目录列表,以处理下一个命令 FINDSTR .

The list of subdirectories output by DIR to STDOUT is redirected with | to handle STDIN of next command FINDSTR.

FINDSTR 在从 STDIN

    由于/I
  • 不区分大小写
  • 从字面上讲是由于/L
  • 由于/X
  • 而用于整行
  • 对于用/G:"..."
  • 指定的文件中列出的任何字符串
  • 由于/V(结果未验证)而将与列表文件中的任何搜索字符串匹配的所有行输出到 STDOUT .
  • case-insensitive because of /I
  • literally because of /L
  • for entire lines because of /X
  • for any string listed in file specified with /G:"..."
  • and outputs to STDOUT all lines NOT matching any search string in list file because of /V (inVerted result).

对于给定示例, FINDSTR 的输出为:

The output of FINDSTR for the given example is:

GHI
JKL

具有 DIR FINDSTR 的整个命令行由 FOR 在以cmd.exe /C开头的后台命令过程中执行. FOR 将在此命令过程中输出的所有内容捕获到 STDOUT 并逐行处理.

The entire command line with DIR and FINDSTR is executed by FOR in a background command process started with cmd.exe /C. FOR captures everything output in this command process to STDOUT and processes it next line by line.

在Windows命令解释器解析整个 FOR 命令行时,重定向操作符|>必须在此处转义,并使用脱字符号^首先将其解释为原义字符.否则,由于命令 FOR 的重定向操作符放置不正确,Windows命令解释器将在 FOR 命令行上退出批处理.

The redirection operators | and > must be escaped here with caret character ^ to be interpreted first as literal characters when Windows command interpreter parses the entire FOR command line. Otherwise Windows command interpreter would exit batch processing on FOR command line because of misplaced redirection operators for command FOR.

所以 FOR 最终在后台执行而不显示窗口:

So FOR finally executes in background without displaying a window:

cmd.exe /C dir "F:\Documents\Batch\Practice folder\*" /AD /B 2>nul | C:\Windows\System32\findstr.exe /I /L /V /X  /G:"F:\Documents\Batch\my folders.txt"

循环变量I包含在每个循环上运行的目录名,该目录名没有在F:\Documents\Batch\Practice folder中找到的路径,并且未在列表文件F:\Documents\Batch\my folders.txt中列出.执行的命令 RD 会悄悄地(/Q)删除该目录及其所有子目录(/S).

The loop variable I contains on each loop run a directory name without path found in F:\Documents\Batch\Practice folder and not listed in list file F:\Documents\Batch\my folders.txt. The executed command RD deletes quietly (/Q) this directory with all its subdirectories (/S).

要了解所使用的命令及其工作方式,请打开命令提示符窗口,在其中执行以下命令,并非常仔细地阅读每个命令显示的所有帮助页面.

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.

  • dir /?
  • echo /?
  • endlocal /?
  • findstr /?
  • for /?
  • rd /?
  • set /?
  • setlocal /?
  • dir /?
  • echo /?
  • endlocal /?
  • findstr /?
  • for /?
  • rd /?
  • set /?
  • setlocal /?

还请阅读有关使用命令重定向操作符的Microsoft文章.以及为什么在命令行上使用"set var = text"后,为什么没有字符串与"echo%var%"一起输出? a>解释了为什么建议使用set "variable=value"代替set variable="value"的原因,因为第一个"的位置在Windows命令解释器的解释中有很大的不同.

Read also the Microsoft article about Using Command Redirection Operators. And the answer on Why is no string output with 'echo %var%' after using 'set var = text' on command line? explains why it is recommended to use set "variable=value" instead of set variable="value" because the position of first " makes a big difference in interpretation by Windows command interpreter.

这篇关于批处理-删除文件夹中除文本文件中列出的文件夹以外的所有文件夹的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆