Как остановить пакетный скрипт при ошибке del

У нас есть пакетный скрипт, который удаляет файлы (del) и каталоги (rd). Кто-нибудь знает, как остановить (сбой) выполнение скрипта, если какой-либо из этих операторов удаления не работает? Они могут выйти из строя, если файл/каталог заблокирован Windows. Спасибо.

Обновить

Заявления, которые я использую:

Дел: del *.* /S /Q

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


person Marcus Leon    schedule 18.02.2009    source источник


Ответы (10)


Для удаления файлов вы можете сначала попытаться 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
)
person Patrick Cuff    schedule 18.02.2009
comment
Это не работает для запуска файла образа процесса. Когда вы запускаете notepad.exe, вы можете успешно переименовать его, но вы не можете удалить его файл изображения. То же самое для загруженных DLL. - person wqw; 11.05.2011

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
)
person Jason Punyon    schedule 18.02.2009
comment
Хорошее предложение, за исключением того, что я удаляю несколько файлов (см. отредактированный пост), поэтому сложно выполнить оператор существования для каждого каталога/файла. - person Marcus Leon; 18.02.2009

EDIT: Правильно, поэтому del неправильно устанавливает ERRORLEVEL. См. ERRORLEVEL в DEL и Команда удаления Windows может завершиться автоматически

ПРЕДЫДУЩЕЕ (неверное) РЕШЕНИЕ

Вы должны проверить файл errorlevel.

Например:

del file.txt
if errorlevel 1 goto FAIL
:PASS
echo Worked!
goto :END

:FAIL
echo Failed!
exit /B 1

:END
person grammar31    schedule 18.02.2009
comment
Не работает: C:\›test.bat C:\›del boo.doc boo.doc. Процесс не может получить доступ к файлу, так как он используется другим процессом. C:\›если уровень ошибки 1 перейти к FAIL C:\›echo Работает! Работал! C:\›Эхо не удалось! Не удалось! C:\›выход /B 1 - person Marcus Leon; 18.02.2009

Вот мой предпочтительный способ проверки ошибок при удалении файлов. Мы перенаправляем «вывод ошибок» (стандартный файл «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
)
person JoelFan    schedule 01.06.2010

Вот укороченная версия варианта мониторинга результатов. Это использует трюк 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%
person wqw    schedule 11.05.2011

Просто чтобы ты знал. Команда DEL действительно возвращает код ошибки, если возникает серьезная ошибка, однако ее поведение выходит далеко за рамки нашей интуиции, когда люди просто верят, что код ошибки вообще не работает.

Это то, что я тестировал в команде DEL в Windows 7:

  • Успешное удаление всех файлов: 0 (разумеется)
  • Некоторые файлы удалены, некоторые файлы отсутствуют: 0 (интуиция ожидает 1)
  • Ошибка удаления из-за отсутствия разрешения или носителя только для чтения: 0 (интуиция ожидает ≥ 1)
  • Несуществующий диск или диск не готов (например, нет компакт-диска в дисководе для компакт-дисков): 1 (да, понятно, но я ожидаю более высокий код ошибки)
  • Неверный путь: 1 (я также ожидаю более высокий код ошибки)

И, если вы укажете список файлов для команды DEL, где хотя бы один из файлов соответствует двум последним видам ошибок, упомянутым выше, то ни один из файлов в списке не будет удален вообще .

person Explorer09    schedule 18.08.2015

Есть сценарий, который будет работать как шарм. Он проверяет отказ удаления, проверяя существование предположительно удаленного файла/каталога.

На выходе будет существующий каталог 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
person Gryzorz    schedule 19.02.2013

Кажется, они работают для меня:

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 )

А вот о производительности понятия не имею.

Вы можете добавить флаг /F в DEL для режима «принудительного удаления».

person jhyot    schedule 22.05.2015


Привет, это тоже должно работать

@echo off  

for /f %%i in ('del notepad2.exe 2^>^&1') do set ERRORLEVEL=1
IF %ERRORLEVEL%=1 then exit
person Gaurav Kolarkar_InfoCepts    schedule 06.03.2013
comment
Вы должны НИКОГДА не устанавливать переменную ERRORLEVEL напрямую. Значение, определенное пользователем, переопределит динамическое значение. %ERRORLEVEL% больше не будет сообщать о возвращенном коде ошибки предыдущей команды. Вместо этого он навсегда расширится до установленного вами значения. - person dbenham; 06.08.2014