После неудачного перенаправления (из-за несуществующего файла или недостаточного доступа к файлу) значение ErrorLevel
, похоже, не установлено (в следующих примерах файл test.tmp
защищен от записи и файл test.nil
не существует):
>>> (call ) & rem // (reset `ErrorLevel`)
>>> > "test.tmp" echo Text
Access is denied.
>>> echo ErrorLevel=%ErrorLevel%
ErrorLevel=0
>>> (call ) & rem // (reset `ErrorLevel`)
>>> < "test.nil" set /P DUMMY=""
The system cannot find the file specified.
>>> echo ErrorLevel=%ErrorLevel%
ErrorLevel=0
Однако, как только неудачное перенаправление сопровождается оператором условной конкатенации ||
, который запрашивает код выхода, ErrorLevel
устанавливается на 1
, неожиданно:
>>> (call ) & rem // (reset `ErrorLevel`)
>>> (> "test.tmp" echo Text) || echo Fail
Access is denied.
Fail
>>> echo ErrorLevel=%ErrorLevel%
ErrorLevel=1
>>> (call ) & rem // (reset `ErrorLevel`)
>>> (< "test.nil" set /P DUMMY="") || echo Fail
The system cannot find the file specified.
>>> echo ErrorLevel=%ErrorLevel%
ErrorLevel=1
Интересно, что ErrorLevel
остается 0
, когда используется оператор &&
:
>>> (call ) & rem // (reset `ErrorLevel`)
>>> (> "test.tmp" echo Text) && echo Pass
Access is denied.
>>> echo ErrorLevel=%ErrorLevel%
ErrorLevel=0
>>> (call ) & rem // (reset `ErrorLevel`)
>>> (< "test.nil" set /P DUMMY="") && echo Pass
The system cannot find the file specified.
>>> echo ErrorLevel=%ErrorLevel%
ErrorLevel=0
ErrorLevel
остается также 0
с помощью оператора &
:
>>> (call ) & rem // (reset `ErrorLevel`)
>>> (> "test.tmp" echo Text) & echo Pass or Fail
Access is denied.
Pass or Fail
>>> echo ErrorLevel=%ErrorLevel%
ErrorLevel=0
>>> (call ) & rem // (reset `ErrorLevel`)
>>> (< "test.nil" set /P DUMMY="") & echo Pass or Fail
The system cannot find the file specified.
Pass or Fail
>>> echo ErrorLevel=%ErrorLevel%
ErrorLevel=0
В случае появления операторов условной конкатенации &&
и ||
, ErrorLevel
также устанавливается на 1
(если ||
встречается до &&
, обе ветки выполняются как в последнем примере, но Я думаю, это просто потому, что &&
оценивает код выхода предыдущей команды echo
):
>>> (call ) & rem // (reset `ErrorLevel`)
>>> (> "test.tmp" echo Text) && echo Pass || echo Fail
Access is denied.
Fail
>>> echo ErrorLevel=%ErrorLevel%
ErrorLevel=1
>>> (call ) & rem // (reset `ErrorLevel`)
>>> (< "test.nil" set /P DUMMY="") || echo Fail && echo Pass
The system cannot find the file specified.
Fail
Pass
>>> echo ErrorLevel=%ErrorLevel%
ErrorLevel=1
Итак, какова связь между значением ErrorLevel
и оператором ||
, почему ErrorLevel
влияет на ||
? Является ли ||
копирование кода выхода на ErrorLevel
? Возможно ли это только при перенаправлении (неудачных), поскольку они обрабатываются до того, как будут выполнены какие-либо команды?
Еще более странно, я не мог наблюдать обратное поведение - ErrorLevel
0
&&
- при правильном возврате тестовой настройки (то есть замене (call )
на (call)
(сначала установить ErrorLevel
в 1
), очищая атрибут только для чтения файла test.tmp
, создавая файл test.nil
(первая строка не пуста, чтобы избежать set /P
, чтобы установить ErrorLevel
в 1
) и используя расширение файла .bat
, а не .cmd
для тестирования (чтобы избежать set /P
до reset ErrorLevel
до 0
)).
Я наблюдал описанное поведение в Windows 7 и Windows 10.