учитывая, что CMD.EXE печально недокументирован, я не уверен, каким должно быть ожидаемое поведение. Я, конечно, не видел никакой документации о том, что такое ожидаемое поведение. Поэтому я думаю, что вам будет трудно найти кого-либо, кто мог бы дать окончательный ответ о том, является ли какое-либо из поведения ошибкой. Но я согласен, что это, безусловно, непоследовательно и кажется мне, по крайней мере, недостатком дизайна.
Я бы не охарактеризовал ситуацию как хаотичную в том, что поведение определенной команды, кажется, воспроизводимой. Но командир.EXE непоследователен в том, что я не вижу никакого способа предсказать, как любая команда ведет себя без тестирования.
у меня нет объяснений, но у меня есть некоторые уточненные классификации поведения.
перенаправление stdout или stderr на stdin работает отлично, если ни одна команда не пытается что-либо записать в перенаправленный вывод. Странное поведение возникает только при попытке внутренней команды запись в stdout или stderr после перенаправления в stdin.
я расширил ваши тесты, и видели следующие различные поведения:
Перенаправленный STDERR 2>&01
Я не делал исчерпывающего тестирования, но каждая внутренняя команда, которую я тестировал, которая записывает в stderr, немедленно завершит сеанс команды, если stderr был перенаправлен на stdin. Примеры включают в себя:
cd invalidPath 2>&0
vol x 2>&0
copy nonExistentFile 2>&0
move nonExistentFile 2>&0
set nonExistentVariable 2>&0
dir nonExistentFile 2>&0
то, что вы думали, было исключением на самом деле никогда не пишет в stderr. Попробуйте выполнить следующие действия без перенаправления, и вы увидите сообщение об ошибке:
dir nonExistentFIle *
так что нет никаких причин для команды, чтобы завершить сеанс команды, если stderr перенаправляется на стандартный ввод.
DIR выводит сообщение об ошибке, только если не удается найти соответствующий файл по всем предоставленным маскам файлов.
:: This prints an error message
dir nonExistentFile1 nonExistentFile2
:: So this terminates the command session
dir nonExistentFile1 nonExistentFile2 2>&0
Перенаправленный STDOUT 1>&0
здесь поведение я видел для перенаправления вывода:
1) выход исчезает в эфир, без какого-либо сообщения об ошибке.
примеры:
vol >&0
copy /-y file1 existingFile2 >&0
move /-y file1 existingFile2 >&0
2) Вывод не выполняется и выводится сообщение об ошибке stderr. Одна команда может создавать несколько сообщений, по одному для каждой неудачной попытки записи в stdout.
примеры:
cd >&0
echo Hello >&0
:: This generates 2 error messages, one for the time,
:: and another for the subsequent empty line
time /t >&0
3) выход терпит неудачу, и пакетная обработка завершенный. Активные SETLOCAL остаются в силе, даже после завершения пакета, если ошибка происходит в пределах вызываемой подпрограммы. В этом отношении он ведет себя так же, как фатальная синтаксическая ошибка.
до сих пор я видел только одну команду демонстрируют такое поведение:
dir >&0
Я ожидал бы, что команда DIR создаст сообщение об ошибке для каждой попытки вывода строки. Но это, кажется, завершается после сбоя на первой строке, и пакетная обработка также прерванный.
4) некоторые команды демонстрируют несколько моделей поведения.
примеры:
:: This SET command generates an error message for each
:: defined variable (behavior 2)
set >&0
:: But this SET command fails to display the prompt without
:: error message (behavior 1). Note that the echo of user input
:: is written directly to :con. It does not use stdout or stderr.
set "var=prompt" >&0
:: A single PAUSE exhibits both behaviors 1 and 2. The prompt to
:: press a key simply dissapears, and the echo of the user input
:: generates an error. Note that in this case, the echo of user
:: input is written to stdout.
pause >&0