清除多个目录-简化当前代码

时间:2019-01-20 13:29:24

标签: batch-file

我正在使用批处理文件删除设置目录中的文件和文件夹。但想知道是否有一种方法可以将当前代码简化为仅几行,而不是针对不同目录重复每一行。

下面是我当前的代码。

main_database

2 个答案:

答案 0 :(得分:2)

@echo off
    setlocal enableextensions disabledelayedexpansion

    for %%a in ( 
        "C:\Users\Testing\Documents" 
        "C:\Users\Testing\Downloads" 
        "C:\Users\Testing\My Pictures"
    ) do pushd %%a && (
        rmdir . /s /q
        popd
    )

使用for命令来迭代文件夹列表。对于列表中的每个文件夹,请尝试将活动目录更改为列表中的当前元素(pushd),如果可以完成(条件执行操作符&&),则删除其中的任何内容(rmdir . /s /q)并还原以前的活动目录(popd

注释在先前的代码中,rmdir . /s /q尝试删除文件夹和文件夹本身中的所有内容。无法删除该文件夹,因为我们已根据pushd的使用将其设置为当前活动目录。正如dbenham在评论中所指出的,这意味着rmdir将显示一条错误消息,指出该文件夹由于正在使用中而无法删除。虽然这是预期的行为(文件夹保护,而不是错误消息),但可能希望隐藏该错误消息。可以通过将错误输出流(流2)重定向到nul设备来完成:

    ...
    ) do pushd %%a && (
        rmdir . /s /q 2>nul 
        popd
    )

这将隐藏与rmdir命令相关的任何错误(无论是否发生)。

可以扩展此技术以隐藏先前代码中的任何错误(如果您包括不存在的文件夹,则pushd还会显示错误)。

@echo off
    setlocal enableextensions disabledelayedexpansion

    2>nul (
        for %%a in ( 
            "C:\Users\Testing\Documents" 
            "C:\Users\Testing\Downloads" 
            "C:\Users\Testing\My Pictures"
        ) do pushd %%a && (
            rmdir . /s /q
            popd
        )
    )

或者,如果您喜欢选择性错误报告(dbenham的想法),则可以将其扩展为:

@echo off
    setlocal enableextensions disabledelayedexpansion

    for %%a in ( 
        "C:\Users\Testing\Documents" 
        "C:\Users\Testing\Downloads" 
        "C:\Users\Testing\My Pictures"
    ) do ( 2>nul pushd "%%~a" ) && (
        rmdir . /s /q 2>&1 | findstr /lb "."
        popd
    )

将隐藏pushd命令中的错误(如果该文件夹不存在,则无需清除它),并且将显示rmdir命令中与任何不可移动元素相关的任何错误当前的活动目录。

答案 1 :(得分:2)

首先,RD /S /Q命令将删除子目录中的所有文件,因此您可以从/S命令中删除DEL选项。

现在您有一个实际的问题-当然,还有一种更好的方法:-)

任意复杂代码的通用解决方案是将所有通用代码放入带有一个或多个参数的子例程中,然后为每组唯一的参数调用该子例程。确保在任何子例程之前包含exit /b,以确保您的主脚本不会在没有调用的情况下不属于子例程代码。

@echo off
call :del "C:\Users\Testing\Documents"
call :del "C:\Users\Testing\Downloads"
call :del "C:\Users\Testing\My Pictures"
exit /b

:del
del /a /f /q /s "%~1\*.*"
for /d %%p in ("%~1\*.*") do rd /s /q "%%p"
exit /b

如果需要,可以添加一个额外的FOR循环来迭代文件,然后只需要一个CALL语句即可。

@echo off
for %%P in (
  "C:\Users\Testing\Documents"
  "C:\Users\Testing\Downloads"
  "C:\Users\Testing\My Pictures"
) do call :del %%P
exit /b

:del
del /a /f /q /s "%~1\*.*"
for /d %%p in ("%~1\*.*") do rd /s /q "%%p"
exit /b

但是由于您的通用代码非常简单,所以我建议通过添加括号将子例程代码移至外部DO块内:

@echo off
for %%P in (
  "C:\Users\Testing\Documents"
  "C:\Users\Testing\Downloads"
  "C:\Users\Testing\My Pictures"
) do (
  del /a /f /q /s "%%~P\*.*"
  for /d %%p in ("%%~P\*.*") do rd /s /q "%%p"
)

这并不能真正减少案例的行数,但是可以使脚本的重复性更加明显并且易于管理。当您在外部循环中添加更多路径时,它将减少代码行。