Почему ErrorLevel устанавливается только после || оператор при неудачном перенаправлении?
При неудачном перенаправлении (из-за несуществующего файла или недостаточного доступа к файлу),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
сброситьErrorLevel
в0
)).
Я наблюдал описанное поведение в Windows 7 и Windows 10.