目的是删除所有文件夹(及其子文件夹),但名称在文本文件中列出的文件夹除外。
文本文件为"F:\Documents\Batch\my folders.txt"
,内容为
ABC
DEF
要删除的文件夹位于"F:\Documents\Batch\Practice folder"
。它包含以下文件夹:ABC
,DEF
,GHI
和JKL
。
运行我的批处理文件后,只应保留ABC
和DEF
,并删除所有其他文件夹(GHI
,JKL
)
以下是我尝试的内容:
@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
请帮助我找到更有效和/或更短的方法。
编辑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:\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
答案 0 :(得分:1)
for /d %%G in (*) do
处理当前目录中的每个非隐藏子目录,其中循环变量G
包含在每个循环上运行没有路径的子目录的名称。 FOR 会忽略具有隐藏属性集的子目录。
由于启用了延迟环境变量扩展,所讨论的 FOR 循环对包含一个或多个感叹号的目录名称不起作用。 %%G
扩展为当前目录名称,当此名称包含!
时,感叹号将被解释为环境变量名称的开头或结尾。因此,两个感叹号之间的所有内容都被环境变量的当前值替换,其中name是两个感叹号之间的字符串,或者更可能在没有该名称的环境变量的情况下没有任何内容。从目录名称中删除单个(剩余)感叹号。在由启用的延迟扩展引起的额外预处理之后,(其余)目录名称实际上由适当的命令进一步处理,如 IF 和 RD 无法删除被操纵的目录或删除错误的目录。
此任务的批处理文件也适用于名称中包含一个或多个感叹号的隐藏子目录和目录:
@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
此批处理文件也可以优化为单行。
@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
(属性目录)目录F:\Documents\Batch\Practice folder
中的子目录列表由于{{1}而采用裸格式这意味着只有没有路径的目录名。 DIR 输出这些选项也是隐藏属性设置的子目录。
对于给定的示例,输出列表为:
/B
DIR 输出错误消息以处理 STDERR ,如果它找不到指定目录中的任何子目录或指定的目录根本不存在它不能找到指定的文件而不是目录。通过将ABC
DEF
GHI
JKL
重定向到设备 NUL ,可以抑制这种可能且误导性的错误消息。
DIR 输出到 STDOUT 的子目录列表将被重定向到2>nul
以处理下一个命令的 STDIN FINDSTR 强>
FINDSTR 搜索从 STDIN
中读取的子目录列表|
,/I
/L
,/X
/G:"..."
(inVerted结果)。给定示例的 FINDSTR 输出为:
/V
在以GHI
JKL
开头的后台命令进程中, DIR 和 FINDSTR 的整个命令行由 FOR 执行。 FOR 将此命令进程中的所有输出捕获到 STDOUT 并逐行处理。
当Windows命令解释器解析整个 FOR cmd.exe /C和|
必须使用符号字符>
进行转义,首先解释为文字字符>命令行。否则Windows命令解释程序将退出 FOR 命令行上的批处理,因为命令 FOR 的重定向操作符错位。
所以 FOR 最终在后台执行而不显示窗口:
^
循环变量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
中列出。执行的命令 RD 将及其所有子目录(F:\Documents\Batch\my folders.txt
)静默删除(/Q
)此目录。
要了解使用的命令及其工作原理,请打开命令提示符窗口,执行以下命令,并完全阅读为每个命令显示的所有帮助页面。
/S
dir /?
echo /?
endlocal /?
findstr /?
for /?
rd /?
set /?
另请阅读有关Using Command Redirection Operators的Microsoft文章。 Why is no string output with 'echo %var%' after using 'set var = text' on command line?上的答案解释了为什么建议使用setlocal /?
代替set "variable=value"
,因为第一个set variable="value"
的位置会对Windows命令解释器的解释产生很大影响。< / p>