如何在批处理脚本中遇到删除失败时停止执行

10
我们有一个批处理脚本,用于删除文件(del)和目录(rd)。 如果这些删除语句中的任何一个失败,有人知道如何停止(失败)脚本的执行吗?如果Windows锁定了文件/目录,则它们可能会失败。谢谢。
更新:
我正在使用以下语句:
删除:del *.* /S /Q RD:FOR /D %%G in (*) DO RD /s /q %%G
10个回答

13

删除文件时,您可以先尝试使用ren(重命名)文件。如果文件被锁定,ren将设置ERRORLEVEL为1。在文件名周围添加引号。

@echo OFF

:: Delete all files, but exit if a file is locked.
for %%F in (*.*) do (
    @echo Deleting %%F
    ren "%%F" tmp 2> nul
    if ERRORLEVEL 1 (
        @echo Cannot delete %%F, it is locked.
        exit /b 1
    )
    del tmp
)

我怀疑你也可以对目录执行同样的操作,但是我似乎无法弄清楚如何锁定目录以便测试。下面的方法可能有效:

:: Remove all directories, but exit if one is locked.
FOR /D %%G in (*) DO (
    @echo Removing %%G
    ren "%%G" tmpdir 2> nul
    if ERRORLEVEL 1 (
        @echo Cannot remove %%G, it is locked
        exit /b 1
    )
    RD /s /q tmpdir
)

1
这对于正在运行的进程图像文件无效。当您启动 notepad.exe 时,可以成功地重命名它,但是您无法删除其图像文件。对于已加载的 DLL 文件也是如此。 - wqw

8

如果文件被锁定,DEL命令不会返回错误级别。我刚刚用Excel文件做了一个测试,在Windows XP上看到的是零。

在执行删除操作之后,最好使用IF EXIST来检查文件是否存在。

del file.txt
if exist file.txt ECHO "FAIL"

编辑后 免责声明:我不知道这个的表现如何...

你可以对这些文件进行操作。

DIR /B /S /A-d > c:\filestodelete.txt

del *.* /S /Q    

FOR /F %%i in (c:\filestodelete.txt) DO (
    IF EXIST %%i ECHO %%i STILL EXISTS
)

然后是针对目录的。
DIR /B /S /Ad > c:\directoriestodelete.txt

FOR /D %%G in (*) DO RD /s /q %%G    

FOR /F %%i in (c:\directoriestodelete.txt) DO (
    IF EXIST %%i ECHO %%i STILL EXISTS
)

好的建议 - 但我正在删除多个文件(请参见编辑后的帖子),因此很难为每个目录/文件执行存在语句。 - Marcus Leon

3

似乎无法工作:C:>test.batC:>del boo.docboo.doc。该进程无法访问该文件,因为它正在被另一个进程使用。C:>if errorlevel 1 goto FAILC:>echo Worked!操作成功!C:>echo Failed!失败!C:>exit /B 1 - Marcus Leon
文档的URL已经失效。 - Mat Lipe

1

仅供参考。DEL命令如果发生严重错误,确实会返回错误代码,但它的行为远远超出了我们的直觉,人们可能会认为错误代码根本不起作用。

这是我在Windows 7中测试DEL命令的结果:

  • 成功删除所有文件:0(当然)
  • 删除了一些文件,一些文件丢失:0(直觉预计为1)
  • 由于没有权限或只读介质而导致删除失败:0(直觉预计≥1)
  • 不存在的驱动器或驱动器未准备好(例如CD-ROM驱动器上没有CD):1(是的,你明白了,但我会期望更高的错误代码)
  • 无效路径:1(我也会期望更高的错误代码)

而且,如果您指定一个文件列表给DEL命令,其中至少有一个文件符合上述最后两种错误类型,则列表中的所有文件都不会被删除


1
这是我检查删除文件错误的首选方法。我们将“错误输出”(标准文件“2”)重定向到一个文件(例如delCmd.err)。然后,我们使用FOR命令作为访问~z“文件大小”操作符的一种方式。如果输出文件的大小不为0,则我们知道“del”出现了错误...我们使用“type”命令显示错误,并以非零错误代码退出批处理文件:
del unwanted.txt 2> delCmd.err
FOR /F "usebackq" %%A IN ('delCmd.err') DO set size=%%~zA
if not "%size%"=="0" (
    echo Error deleting unwanted.txt
    type delCmd.err
    exit /B 1
)

1
这是结果监控变体的简短版本。它使用2>&1技巧将stderr重定向到stdout,并使用for /f检查任何输出。
@echo off
setlocal
set error=0
for /f %%i in ('del notepad2.exe 2^>^&1') do set error=1
echo %error%

0

有一个脚本可以完美地工作。 它通过测试所谓已删除的文件/目录的存在来测试删除失败。

输出将是一个完全空内容的现有c:\mydirectory。 任何错误都会中断进程并报告。

唯一的缺点是,目录被递归地删除,因为没有简单的方法从最“子”目录开始删除目录。

@echo OFF
set path_to_clean=c:\mydirectory

@echo -Deleting Files
dir /A-D /S /B %path_to_clean%\* > fileslist.txt
for /F %%F in (fileslist.txt) do (
    @echo Deleting %%F
    del %%F 2> nul
    if exist %%F (
        @echo Cannot delete %%F, it is locked.
        goto errorhandling
    )
)
del fileslist.txt
@echo -Deleting Files done

@echo -Deleting Directories
dir /AD /B %path_to_clean%\* > directorieslist.txt

for /F %%D in (directorieslist.txt) do (
    @echo Deleting %path_to_clean%\%%D
    rmdir /S /Q %path_to_clean%\%%D 2> nul
    if exist %path_to_clean%\%%D (
        @echo Cannot delete %path_to_clean%\%%D. This folder or one of its sub-directories is locked.
        goto errorhandling
    )
)
del directorieslist.txt
@echo -Deleting Directories done

:errorhandling
rem some code here

0

这些对我来说似乎有效:

RD:

FOR /D %d IN (*) DO ( RD /S /Q "%d" & IF EXIST "%d" EXIT /B 1 )

删除:

FOR %f IN (*.*) DO ( DEL /Q "%f" & IF EXIST "%f" EXIT /B 1 )

不过性能方面我没有什么想法。

你可以在DEL命令后加上/F标志来强制删除。


-1

对于 rdrmdir,您可以执行以下操作

rd "some directory" || rem

这将正确设置错误级别 - 查看


不幸的是,这个技巧在DEL命令中不起作用 :-( - dbenham
1
另外,rd命令并不会为所有错误情况(例如访问被拒绝)设置errorlevel。 - jhyot

-2

嗨,这也应该可以工作

@echo off  

for /f %%i in ('del notepad2.exe 2^>^&1') do set ERRORLEVEL=1
IF %ERRORLEVEL%=1 then exit

3
您绝不能直接设置ERRORLEVEL变量,因为用户定义的值将覆盖动态值。%ERRORLEVEL%将不再报告前一个命令的返回错误代码。相反,它将永久扩展为您所设置的值。 - dbenham

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接