Придушити вихід командного рядка


118

У мене такий простий пакетний файл:

відлуння

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

пауза

Якщо "test.exe" не працює, я отримую це повідомлення:

ПОМИЛКА. Процес "test.exe" не знайдено.

Чому це повідомлення про помилку відображається, навіть якщо я перенаправляв вихід на NUL?

Як я можу придушити цей результат?

Відповіді:


212

Тому що повідомлення про помилки часто йдуть stderrне stdout.

Змініть виклик на це:

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

і все буде краще.

Це працює тому, що stdoutце дескриптор файлів 1, і stderrце дескриптор файлів 2 за умовою. (0 stdin, до речі,.) 2>&1Копіює дескриптор файлу 2 виводу з нового значення 1, яке щойно переспрямовано на нульовий пристрій.

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

Оновлення: Я знаю, що ОП розуміє особливість "файлу", який називається, про який NULя пишу сюди, але коментатор не зробив цього, і тому дозвольте мені подати докладнішу інформацію з цього приводу.

Повертаючись до самих ранніх версій MSDOS, ядра файлової системи попередньо вибирали деякі імена файлів і використовувались для позначення пристроїв. Найраніший список цих імен , включених NUL, PRN, CON, AUXі COM1через COM4. NULє нульовим пристроєм. Його завжди можна відкрити для читання чи написання, на ньому може бути записана будь-яка кількість, і читання завжди вдається, але не повертає жодних даних. До інших належать паралельний порт принтера, консоль та до чотирьох послідовних портів. Щодо MSDOS 5, було ще кілька зарезервованих імен, але основна конвенція була дуже чітко встановлена.

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

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

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


5
Дякую за відповідь, а найбільше за пояснення.
JosephStyons

Рекомендація: taskkill /im "test.exe" /f >%temp%\nul 2>&1 & del %temp%\nul. Це не дозволить пустому нульовому файлу розміститись у локальному каталозі
Samy Bencherif

11
@SamyBencherif, NUL- це зарезервоване ім’я файлу і відображається на пристрої NUL. Ви не можете створити фактичний файл, названий NULу будь-якому каталозі.
RBerteig

7

Використовуйте цей сценарій замість цього:

@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 байт.

Найкоротша версія вашого сценарію може бути: символ використовується для перенаправлення в перший раз, і для поділу команд , вдруге. Символ не потрібно двічі в одну лінію. Цей код складає всього 40 байт, незважаючи на те, що ви розмістили 49 байт! Я фактично врятував 9 байт. Щоб отримати більш чистий код, дивіться вище.
@taskkill/f /im test.exe >nul 2>&1&pause
&
@


Так, я знаю, що половина публікації - це, як скоротити код.
EKons

3

mysqldump не працює з: > nul 2> & 1
Замість цього використовувати: 2> nul
Це придушує повідомлення stderr: "Попередження: Використання пароля в інтерфейсі командного рядка може бути небезпечним"


0

Ви можете зробити це і замість цього:

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

Незважаючи на те, що контекст питання стосувався пакетних сценаріїв, я виявив, що в PowerShell вищевказаний синтаксис не відповідає " out-file: FileStream було запропоновано відкрити пристрій, який не є файлом. Для підтримки таких пристроїв, як 'com1:' або 'lpt1: ', викликайте CreateFile, а потім використовуйте конструктори FileStream, які приймають ручку ОС як IntPtr. "Рішення полягає в заміні > nulна >$null.
водозлив
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.