コマンドライン出力を抑制


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であるため機能します。(stdinちなみに0はです。)2>&1コピーは、nullデバイスにリダイレクトされたばかりの新しい値1から出力ファイル記述子2をコピーします。

この構文は(大まかに)多くのUnixシェルから借用されていますが、シェル構文とCMD.EXEの間には微妙な違いがあるため、注意する必要があります。

更新: OP NULがここに書き込む名前の「ファイル」の特殊な性質を理解していることはわかっていますが、コメンターは理解していなかったため、その側面についてもう少し詳しく説明します。

MSDOSの最初のリリースまでさかのぼると、特定のファイル名はファイルシステムカーネルによって横取りされ、デバイスの参照に使用されていました。それらの名前の最も初期のリストが含まれNULPRNCONAUXCOM1COM4NULnullデバイスです。読み取りまたは書き込み用に常に開くことができ、任意の量を書き込むことができ、読み取りは常に成功しますが、データは返しません。その他には、パラレルプリンターポート、コンソール、および最大4つのシリアルポートが含まれます。MSDOS 5の時点で、さらにいくつかの予約名がありましたが、基本的な規則は非常によく確立されていました。

Windowsが作成されたとき、それはMSDOSカーネルの上にあるかなり薄いアプリケーションスイッチングレイヤーとして始まったため、同じファイル名の制限がありました。Windows NTがそれ自体で真のオペレーティングシステムとして作成されたとき、NULおよびのような名前は、COM1それらを排除できるほど機能するとは考えられていませんでした。ただし、新しいデバイスが常に実際のファイルのそれらの名前の将来のユーザーをブロックする名前を取得するという考えは、明らかに不合理です。

Windows NTとそれに続くすべてのバージョン(2K、XP、7、および現在8)はすべて、カーネルコードから、さらに注意深く構築された、移植性の低いユーザー空間コードに、より複雑なNT名前空間を使用します。その名前空間では、デバイスドライバーは\Deviceフォルダーを通じて表示されます。必要な下位互換性をサポートするため\DosDevicesに、ファイルシステムフォルダー内の予約済みファイル名のリストを実装するフォルダーを使用する特別なメカニズムがあります。ユーザーコードは、通常のWin32 APIの下のAPIレイヤーを使用して、この内部名前空間を参照できます。カーネルの名前空間を探索するための良いツールがあるWinObj MicrosoftのSysInternalsのグループから。

Windowsでのファイル(およびデバイス)の正当な名前を取り巻く規則の完全な説明については、MSDNのこのページは有益であり、困難なものになります。ルールは多くのより多くの彼らがあるべきよりも複雑で、そして「どのくらいの時間、最長法的完全修飾パス名は?」など、いくつかの簡単な質問に答えるために、実際には不可能です。


5
答えてくれてありがとう、そして何よりも説明してくれました。
JosephStyons 2009

推奨事項:taskkill /im "test.exe" /f >%temp%\nul 2>&1 & del %temp%\nul。これにより、空のnullファイルがローカルディレクトリに配置されなくなります
Samy Bencherif '26

11
@SamyBencherif NULは予約されたファイル名で、NULデバイスにマップされます。NULどのディレクトリでもという名前の実際のファイルを作成することはできません。
RBerteig 2013

7

代わりにこのスクリプトを使用してください:

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

この2>&1部分が実際に行うことは、stderr出力をにリダイレクトすることstdoutです。以下で詳しく説明します。

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

タスク「test.exe」を終了します。にリダイレクトstderrstdoutます。次に、にリダイレクトstdoutnulます。

@一時停止

Press any key to continue . . . 誰かがキーを押すまで、一時停止メッセージを表示します。

注:@記号は、各コマンドのプロンプトを非表示にしています。この方法で最大8バイトを保存できます。

スクリプトの最短バージョンは次のようになります
@taskkill/f /im test.exe >nul 2>&1&pause
&文字は最初にリダイレクトに使用され、2回目にコマンドを分離するために使用されます。文字が並んで二度必要とされていません。あなたが投稿したものは49バイトですが、このコードは40バイトです!実際に9バイト節約しました。よりクリーンなコードについては、上記を参照してください。
@


はい、私は投稿の半分が実際にコードを短縮する方法であることを知っています。
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: 」のIntPtrとしてOSハンドルを取るのFileStreamコンストラクタを使用し、その後、のCreateFileを呼び出します。」ソリューションは、交換することである> nul>$null
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.