目标是删除所有文件夹(及其子文件夹),但名称列在文本文件中的文件夹除外。
文本文件为"F:DocumentsBatchmy folders.txt"
,内容为
ABC
DEF
要删除的文件夹位于"F:DocumentsBatchPractice folder"
中。它包含以下文件夹:ABC
、DEF
、GHI
和JKL
。
运行我的批处理文件后,应该只保留ABC
和DEF
,并且应该删除所有其他文件夹(GHI
、JKL
)
以下是我尝试过的:
@echo off
set WORKDIR="F:DocumentsBatchPractice folder"
set LISTFILES="F:DocumentsBatchmy 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
请帮我找到一种更有效和/或更短的方法。
编辑1:该代码将删除所有与LISTFILES
中的名称匹配的文件夹。但当我做任何事情时:
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
),都会删除所有文件夹。所以,我尝试了这个,它工作
@echo off
setlocal enableDelayedExpansion
set WORKDIR="D:IFXservices4"
set LISTFILES="D:IFXservicesfiles.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循环不适用于包含一个或多个感叹号的目录名。%%G
被扩展为当前目录名,当该名称包含!
时,感叹号被解释为环境变量名的开始或结束。所以,两个感叹号之间的所有内容都被环境变量的当前值所取代,name是两个惊叹号之间的字符串,如果不存在具有该名称的环境变量,则更有可能不包含任何内容。将从目录名中删除一个(剩余的)感叹号。在启用延迟扩展导致的额外预处理之后,(剩余的)目录名实际上会由适当的命令进一步处理,如IF和RD无法删除操作的目录或删除错误的目录。
此任务的批处理文件也适用于名称中有一个或多个感叹号的隐藏子目录和目录,它是:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "WORKDIR=F:DocumentsBatchPractice folder"
set "LISTFILE=F:DocumentsBatchmy folders.txt"
for /F "eol=| delims=" %%I in ('dir "%WORKDIR%*" /AD /B 2^>nul ^| %SystemRoot%System32findstr.exe /I /L /V /X /G:"%LISTFILE%"') do rd /Q /S "%WORKDIR%%%I"
endlocal
此批处理文件也可以优化为单行。
@for /F "eol=| delims=" %%I in ('dir "F:DocumentsBatchPractice folder*" /AD /B 2^>nul ^| %SystemRoot%System32findstr.exe /I /L /V /X /G:"F:DocumentsBatchmy folders.txt"') do @rd /Q /S "F:DocumentsBatchPractice folder%%I"
由于/AD
(属性目录),dir "F:DocumentsBatchPractice folder*" /AD /B
输出以处理STDOUT由于/B
,目录F:DocumentsBatchPractice folder
中的子目录列表为空格式,这意味着只有目录名而没有路径DIR具有这些选项的输出也是具有隐藏属性集的子目录。
对于给定的示例,输出列表为:
ABC
DEF
GHI
JKL
DIR如果在指定目录中找不到任何子目录,或者指定目录根本不存在,即找不到指定的文件而不是目录,则输出一条错误消息来处理STDERR。通过使用2>nul
将此可能的误导性错误消息重定向到设备NUL,可以抑制此错误消息。
DIR输出到STDOUT的子目录列表将使用|
重定向,以处理FINDSTR下一个命令的STDIN。
FINDSTR在从STDIN读取的子目录列表中搜索
由于/I
,- 不区分大小写
- 因为
/L
- 由于
/X
- 对于用
/G:"..."
指定的文件中列出的任何字符串 - 并将由于CCD_ 28(inVerted result)而与列表文件中的任何搜索字符串匹配的所有行NOT输出到STDOUT
对于给定的示例,FINDSTR的输出为:
GHI
JKL
DIR和FINDSTR的整个命令行由FOR在cmd.exe /C
启动的后台命令过程中执行FOR捕获此命令过程中输出到STDOUT的所有内容,并逐行处理。
重定向运算符|
和>
必须在此处使用插入字符^
进行转义,以便在Windows命令解释器解析整个FOR命令行时首先将其解释为文字字符。否则,Windows命令解释器将退出FOR命令行上的批处理,因为命令FOR的重定向运算符位置错误。
因此FOR最终在后台执行而不显示窗口:
cmd.exe /C dir "F:DocumentsBatchPractice folder*" /AD /B 2>nul | C:WindowsSystem32findstr.exe /I /L /V /X /G:"F:DocumentsBatchmy folders.txt"
循环变量I
在每个循环运行中都包含一个目录名,该目录名没有在F:DocumentsBatchPractice folder
中找到的路径,也没有在列表文件F:DocumentsBatchmy folders.txt
中列出。执行的命令RD悄悄删除(/Q
)此目录及其所有子目录(/S
)。
为了理解所使用的命令及其工作方式,请打开命令提示符窗口,在那里执行以下命令,并非常仔细地阅读为每个命令显示的所有帮助页面。
dir /?
echo /?
endlocal /?
findstr /?
for /?
rd /?
set /?
setlocal /?
另请阅读Microsoft关于使用命令重定向运算符的文章。在命令行上使用"set var=text"后,为什么没有用"echo%var%"输出字符串?解释了为什么建议使用set "variable=value"
而不是set variable="value"
,因为第一个"
的位置对Windows命令解释器的解释有很大的不同。