2

У меня есть следующий пакетный скрипт, который работает на FTP-сервере. Я использую планировщик, который передает 4 переменные; SouRCe, EXTension, DESTination и ZIP Directory. Это простой сценарий, который требует первых 3 переменных, но пользователь может опустить последние 4-ые, если им не нужно архивировать файлы.

@ECHO OFF

SET SRC=%1
SET EXT=%2
SET DEST=%3
SET ZIPD=%4
SET DTE=%DATE:~4,2%%DATE:~7,2%%DATE:~10,4%
FOR /F "TOKENS=1-3 DELIMS=: " %%L IN ('TIME /T') DO SET hhmm=%%L%%M%

DIR /B /A:-d %SRC%
IF ERRORLEVEL 1 (
        ECHO *** There are no files to process. *** RC=%ERRORLEVEL%
    SET ERRORLEVEL=0
        GOTO EXIT
)

DEL /Q %SRC%\Thumbs.db

IF DEFINED ZIPD (
    WZZIP %ZIPD%\%DTE%%hhmm%.zip %SRC%\*%EXT%
    IF ERRORLEVEL 1 (
        ECHO *** WZZIP for "%SRC%\*%EXT%" failed. *** RC=%ERRORLEVEL%
        ECHO.
        GOTO EXIT
    )
    ECHO.
    ECHO successfully zipped %SRC% TO %ZIPD%: %DTE%%hhmm%.zip
    ECHO.
)

MOVE /Y %SRC%\*%EXT% %DEST%
IF ERRORLEVEL 1 (
    ECHO ** MOVE "%SRC%\*%EXT%" TO "%DEST%"  Failed. *** RC=%ERRORLEVEL%
)

:EXIT
EXIT /B %ERRORLEVEL%

Проблема, с которой я сталкиваюсь, заключается в том, что если в 8:15 утра в каталоге ничего нет (планировщик запускает его),

DIR /B /A:-d %SRC%

терпит неудачу с уровнем ошибки 1. Это входит в петлю и выходит. Тест на уровень ошибки работает как

IF ERRORLEVEL 1

и в качестве

IF NOT %ERRORLEVEL% == 0

Проблема, с которой я сталкиваюсь, заключается в том, что при любых последующих сбоях пользовательская переменная% ERRORLEVEL% не обновляется. Вот почему я должен использовать IF ERRORLEVEL 1 для других проверок. Теперь, если WZZIP завершается ошибкой, он входит в цикл после команды, но сообщение ECHO выдает «RC = 0», даже если ERRORLEVEL должен был быть больше или равен 1, и поэтому должен был обновить% ERRORLEVEL% до кем бы это ни было. Я тестировал скрипт добавления

ECHO %ERRORLEVEL%

до каждой другой строки, чтобы увидеть изменения, и хотя тест DIR корректно обновляет% ERRORLEVEL%, снова DEL файла thumb.db, который завершается ошибкой 99,999% времени, возвращает% ERRORLEVEL% = 0 и WZZIP, если принудительно завершается неудачей также выходит RC = 0. Пробовал SETLOCAL, SETLOCAL ENABLEEXTENSIONS и кучу других вещей, даже пытался удалить все, кроме части WZZIP, и все равно он не обновляет% ERRORLEVEL%. Это FTP-сервер, на котором мы постоянно запускаем сценарии для передачи файлов, поэтому мне было интересно, может быть, есть какой-то конфликт с другими потоками cmd, изменяющими переменную env во время выполнения моего сценария? Кроме того, большинство других сценариев были написаны не мной, и они ЛЮБЯТ, используя SET ERRORLEVEL=whatevernumber и я знаю, что это вызывало у меня конфликты в прошлом. Мне интересно, может ли это быть виновником.

1 ответ1

1

Вам нужно Delayed Expansion, если вы хотите использовать переменную, которую вы изменили в том же командном блоке. (Командный блок - это серия команд в скобках ( и ) .) Задержанные переменные ссылаются с помощью !var! вместо %var% .

Пример:

@ECHO OFF
SETLOCAL EnableExtensions EnableDelayedExpansion
cmd /C exit /B 99
echo before ^(command block^) %%errorlevel%%=%errorlevel% ^^!errorlevel^^!=!errorlevel!
(
  (call)
  echo ^(inside command block^) %%errorlevel%%=%errorlevel% ^^!errorlevel^^!=!errorlevel!
  (call )
  echo ^(inside command block^) %%errorlevel%%=%errorlevel% ^^!errorlevel^^!=!errorlevel!
)
echo  after ^(command block^) %%errorlevel%%=%errorlevel%  ^^!errorlevel^^!=!errorlevel!

Выход:

==> D:\bat\SU\1113027.bat
before (command block) %errorlevel%=99 !errorlevel!=99
(inside command block) %errorlevel%=99 !errorlevel!=1
(inside command block) %errorlevel%=99 !errorlevel!=0
 after (command block) %errorlevel%=0  !errorlevel!=0

Трюки (call) и (call ) украденные из ответа Дбенхэма на установку ERRORLEVEL в 0 вопрос:

Если вы хотите установить уровень errorlevel 0 , тогда вы можете использовать этот совершенно неинтуитивный, но очень эффективный синтаксис: (call ) .Пробел после звонка имеет решающее значение. Если вы хотите установить уровень errorlevel на 1 , вы можете использовать (call) .Очень важно, чтобы после звонка не было места.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .