2018 年 6 月 1 日发布的所有答案都没有,除了 foxidrive 发布的单个命令行,真正删除了所有文件和所有%PathToFolder% 中的文件夹/目录。这就是使用非常简单的单个命令行发布另一个答案以删除文件夹的所有文件和子文件夹以及具有更复杂解决方案的批处理文件的原因,该解决方案解释了为什么在 2018 年 6 月 1 日发布的所有其他答案使用 RD 的strong>DEL 和 FOR 未能完全清理文件夹。
简单的单命令行解决方案,当然也可以在批处理文件中使用:
pushd "%PathToFolder%" 2>nul && ( rd /Q /S "%PathToFolder%" 2>nul & popd )
此命令行包含三个依次执行的命令。
第一个命令 PUSHD 将当前目录路径压入堆栈,然后将%PathToFolder% 设置为运行命令进程的当前目录。
默认情况下这也适用于UNC 路径,因为默认情况下会启用命令扩展,在这种情况下 PUSHD 创建一个指向该指定网络资源的临时驱动器号,然后更改当前驱动器和目录,使用新定义的驱动器号。
PUSHD如果指定的目录根本不存在,输出以下错误信息来处理STDERR:
系统找不到指定的路径。
通过使用 2>nul 将其重定向到设备 NUL 来抑制此错误消息。
下一条命令RD只有在当前命令进程的当前目录切换到指定目录成功,即指定目录完全存在时才会执行。
带有选项/Q 和/S 的命令RD 会安静地 删除所有子目录 的目录,即使指定的目录包含具有隐藏属性或只读属性集的文件或文件夹。系统属性永远不会阻止删除文件或文件夹。
未删除的是:
-
用作任何正在运行的进程的当前目录的文件夹。如果文件夹用作任何正在运行的进程的当前目录,则无法删除此类文件夹的整个文件夹树。
-
当前由任何正在运行的进程打开的文件,在文件打开时设置了文件访问权限,以防止在正在运行的应用程序/进程打开时删除文件。这样打开的文件还可以防止将整个文件夹树删除到打开的文件中。
-
当前用户没有删除文件/文件夹所需 (NTFS) 权限的文件/文件夹,这也阻止了删除该文件/文件夹的文件夹树。
此命令行使用不删除文件夹的第一个原因来删除指定文件夹的所有文件和子文件夹,但不删除文件夹本身。该文件夹临时成为运行命令进程的当前目录,以防止删除文件夹本身。当然,这会导致命令 RD 输出错误消息:
该进程无法访问该文件,因为它正被另一个进程使用。
File 在这里是错误的术语,因为实际上该文件夹正被另一个进程使用,即执行命令 RD 的当前命令进程。好吧,实际上文件夹是文件系统的一个特殊文件,它具有文件属性 directory,它解释了此错误消息。但我不想深入研究文件系统管理。
与所有其他错误消息一样,由于上述三个原因而可能发生此错误消息,通过使用 2>nul 将其从句柄 STDERR 重定向到设备 NUL。
第三个命令 POPD 独立于命令 RD 的退出值执行。
POPD将PUSHD推送的目录路径从堆栈中弹出,并将运行命令进程的当前目录更改为该目录,即恢复初始当前目录。如果是 UNC 文件夹路径,POPD 会删除由 PUSHD 创建的临时驱动器号。
注意: POPD 可以在初始当前目录是要清理的目录的子目录不再存在的情况下静默地无法恢复初始当前目录。在这种特殊情况下,%PathToFolder% 仍然是当前目录。所以建议不要从%PathToFolder%的子目录运行上面的命令行。
还有一个有趣的事实:
我也尝试了使用 UNC 路径的命令行,方法是共享本地目录 C:\Temp 与共享名称 Temp 并使用 UNC 路径 \\%COMPUTERNAME%\Temp\CleanTest 在 Windows 7 上分配给环境变量 PathToFolder。如果当前目录在运行命令行是使用UNC路径访问的共享本地文件夹的子目录,即C:\Temp\CleanTest\Subfolder1,Subfolder1被RD删除,下一个POPD静默失败生成C:\Temp\CleanTest\Subfolder1再次返回当前目录,导致Z:\CleanTest 保留为正在运行的命令进程的当前目录。因此,在这种非常非常特殊的情况下,临时驱动器号会一直保留,直到当前目录被更改,例如将cd /D %SystemRoot% 更改为真正存在的本地目录。不幸的是,如果 POPD 无法恢复初始当前目录,则它不会以大于 0 的值退出,因此仅使用 POPD 的退出代码就无法检测到这种非常特殊的错误情况.但是,可以假设没有人遇到过这种非常特殊的错误情况,因为 UNC 路径通常不用于访问本地文件和文件夹。
为了更好地理解所使用的命令,请打开命令提示符窗口,在其中执行以下命令,并仔细阅读每个命令显示的帮助。
Single line with multiple commands using Windows batch file 解释了此处使用的运算符 && 和 &。
接下来让我们看看批处理文件的解决方法,使用命令DEL删除%PathToFolder%中的文件,FOR和RD删除%PathToFolder% 中的子文件夹。
@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem Clean the folder for temporary files if environment variable
rem PathToFolder is not defined already outside this batch file.
if not defined PathToFolder set "PathToFolder=%TEMP%"
rem Remove all double quotes from folder path.
set "PathToFolder=%PathToFolder:"=%"
rem Did the folder path consist only of double quotes?
if not defined PathToFolder goto EndCleanFolder
rem Remove a backslash at end of folder path.
if "%PathToFolder:~-1%" == "\" set "PathToFolder=%PathToFolder:~0,-1%"
rem Did the folder path consist only of a backslash (with one or more double quotes)?
if not defined PathToFolder goto EndCleanFolder
rem Delete all files in specified folder including files with hidden
rem or read-only attribute set, except the files currently opened by
rem a running process which prevents deletion of the file while being
rem opened by the application, or on which the current user has not
rem the required permissions to delete the file.
del /A /F /Q "%PathToFolder%\*" >nul 2>nul
rem Delete all subfolders in specified folder including those with hidden
rem attribute set recursive with all files and subfolders, except folders
rem being the current directory of any running process which prevents the
rem deletion of the folder and all folders above, folders containing a file
rem opened by the application which prevents deletion of the file and the
rem entire folder structure to this file, or on which the current user has
rem not the required permissions to delete a folder or file in folder tree
rem to delete.
for /F "eol=| delims=" %%I in ('dir "%PathToFolder%\*" /AD /B 2^>nul') do rd /Q /S "%PathToFolder%\%%I" 2>nul
:EndCleanFolder
endlocal
批处理文件首先确保环境变量PathToFolder 真正定义为使用不带双引号且末尾不带反斜杠的文件夹路径。最后的反斜杠不会有问题,但文件夹路径中的双引号可能会出现问题,因为在批处理文件执行期间PathToFolder 的值与其他字符串连接。
重要的是这两行:
del /A /F /Q "%PathToFolder%\*" >nul 2>nul
for /F "eol=| delims=" %%I in ('dir "%PathToFolder%\*" /AD /B 2^>nul') do rd /Q /S "%PathToFolder%\%%I" 2>nul
DEL命令用于删除指定目录下的所有文件。
- 选项
/A 是处理所有文件所必需的,包括具有隐藏属性的文件,如果不使用选项/A,DEL 会忽略该属性。
-
/F 选项是强制删除带有只读属性集的文件所必需的。
-
/Q 选项是运行多个文件的安静删除所必需的,而不提示用户是否应该真正删除多个文件。
-
>nul 需要将写入处理 STDOUT 的文件名的输出重定向到设备 NUL,由于当前打开文件或用户无法删除该设备 NUL无权删除该文件。
-
2>nul 需要将每个无法从句柄 STDERR 删除的文件的错误消息输出重定向到设备 NUL。
FOR 和 RD 命令用于删除指定目录下的所有子目录。但是 for /D 没有被使用,因为 FOR 在这种情况下忽略了具有隐藏属性集的子目录。因此,for /F 用于在后台以%ComSpec% /c 启动的单独命令进程中运行以下命令行:
dir "%PathToFolder%\*" /AD /B 2>nul
DIR 以裸格式输出,因为/B 具有属性D 的目录条目,即指定目录中的所有子目录的名称独立于其他属性,例如没有路径的隐藏属性。 2>nul 用于将 DIR 在找不到从句柄 STDERR 找到目录的错误消息输出重定向到设备 NUL。
重定向运算符 > 必须在 FOR 命令行上使用插入符 ^ 进行转义,以便在 Windows 命令解释器之前处理此命令行时被解释为文字字符执行命令 FOR,该命令在后台启动的单独命令进程中执行嵌入的 dir 命令行。
FOR 处理捕获的输出,以处理已启动命令进程的 STDOUT,这些输出是不带路径的子目录的名称,并且从不包含在双引号中。
FOR 带有选项 /F 会忽略此处不会出现的空行,因为带有选项 /B 的 DIR 不会输出空行。
FOR 也会忽略以分号开头的行,分号是默认的行尾字符。目录名称可以以分号开头。出于这个原因,eol=| 用于将竖线字符定义为行尾字符,目录或文件的名称中不能包含该字符。
FOR 将使用空格和水平制表符作为分隔符将行拆分为子字符串,并将仅将第一个空格/制表符分隔的字符串分配给指定的循环变量I。此处不需要这种拆分行为,因为目录名称可以包含一个或多个空格。因此delims= 用于定义一个空的分隔符列表以禁用行拆分行为并分配给循环变量I,始终是完整的目录名称。
命令 FOR 为每个目录名称运行命令 RD 而没有路径,这就是 RD 命令行上的文件夹路径的原因必须再次指定它与子文件夹名称连接。
要了解所使用的命令及其工作原理,请打开命令提示符窗口,在其中执行以下命令,并仔细阅读每个命令显示的所有帮助页面。
del /?
dir /?
echo /?
endlocal /?
for /?
goto /?
if /?
rd /?
rem /?
set /?
setlocal /?