Подавить вывод командной строки

У меня есть простой пакетный файл:

echo off

taskkill /im "test.exe" /f > nul

pause

Если "test.exe" не запущен, я получаю это сообщение:

ERROR: The process "test.exe" not found.

Почему это сообщение об ошибке отображается, хотя я перенаправил вывод в NUL?

Как я могу подавить этот вывод?

Ответ 1

Поскольку сообщения об ошибках часто идут в stderr not stdout.

Измените вызов следующим образом:

taskkill /im "test.exe" /f >nul 2>&1

и все будет лучше.

Это работает, потому что stdout является файловым дескриптором 1, а stderr является файловым дескриптором 2 по соглашению. (0 - stdin, кстати.) 2>&1 копирует выходной дескриптор файла 2 из нового значения 1, который был просто перенаправлен на нулевое устройство.

Этот синтаксис (свободно) заимствован из многих оболочек Unix, но вы должны быть осторожны, потому что есть тонкие различия между синтаксисом оболочки и CMD.EXE.

Обновление: Я знаю, что OP понимает особый характер "файла" с именем NUL, который я пишу здесь, но комментатор этого не сделал, и поэтому позвольте мне немного отвлечься более подробно об этом.

Возвращаясь к самым ранним выпускам MSDOS, некоторые имена файлов были выгружены ядром файловой системы и использовались для обозначения устройств. Самый ранний список этих имен включал NUL, PRN, CON, AUX и COM1 через COM4. NUL - это нулевое устройство. Он всегда может быть открыт для чтения или записи, любая сумма может быть написана на нем и всегда читается, но не возвращает никаких данных. К другим относятся порт параллельного принтера, консоль и до четырех последовательных портов. Что касается MSDOS 5, было еще несколько зарезервированных имен, но основное соглашение было очень хорошо установлено.

Когда Windows была создана, она начала работать как довольно тонкий слой переключения приложений поверх ядра MSDOS и, таким образом, имела те же ограничения на имя файла. Когда Windows NT была создана как настоящая операционная система сама по себе, такие имена, как NUL и COM1, слишком широко считались работающими для их устранения. Однако идея о том, что новые устройства всегда будут получать имена, которые блокируют будущего пользователя этих имен для фактических файлов, явно необоснованна.

Windows NT и все версии, которые следуют (2K, XP, 7 и теперь 8), следуют за использованием гораздо более сложного NT Namespace от код ядра и тщательно сконструированный и высоконезависимый код пространства пользователя. В этом пространстве имен драйверы устройств видны через папку \Device. Для поддержки требуемой обратной совместимости существует специальный механизм с использованием папки \DosDevices, которая реализует список зарезервированных имен файлов в любой папке файловой системы. Пользовательский код может просматривать это внутреннее пространство имен с использованием уровня API ниже обычного API Win32; хорошим инструментом для изучения пространства имен ядра является WinObj из группы SysInternals в Microsoft.

Для полного описания правил, связанных с юридическими именами файлов (и устройств) в Windows, эта страница в MSDN будет как информативным, так и пугающий. Правила намного сложнее, чем они должны быть, и на самом деле невозможно ответить на некоторые простые вопросы, такие как "как долго это длинное правовое полное имя пути?".

Ответ 2

Вместо этого используйте script:

@taskkill/f /im test.exe >nul 2>&1
@pause

Что фактически делает часть 2>&1, так это то, что она перенаправляет вывод stderr на stdout. Я объясню это ниже:

@taskkill/f/im test.exe > ​​nul 2 > & 1

Убейте задачу "test.exe". Перенаправить stderr в stdout. Затем переадресуйте stdout в nul.

@pause

Показывать сообщение паузы Press any key to continue . . ., пока кто-то не нажмет клавишу.

ПРИМЕЧАНИЕ. Символ @ скрывает приглашение для каждой команды. Таким образом вы можете сохранить до 8 байтов.

Самая короткая версия вашего script может быть:
@taskkill/f /im test.exe >nul 2>&1&pause
Символ & используется для перенаправления в первый раз и для разделения команд второй раз.
Символ @ не требуется дважды в строке. Этот код составляет всего 40 байт, несмотря на то, что вы разместили 49 байтов! Я фактически сохранил 9 байтов. Для более чистого кода смотрите выше.

Ответ 3

Вы также можете сделать это:

tasklist | find /I "test.exe" > nul && taskkill /f /im test.exe > nul

Ответ 4

mysqldump не работает с: > nul 2 > & 1
Вместо этого используйте: 2 > nul
Это подавляет сообщение stderr: "Предупреждение: использование пароля в интерфейсе командной строки может быть небезопасным"