명령 줄 출력 억제


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>&1null 장치로 방금 리디렉션 된 새 값 1에서 출력 파일 설명자 2를 복사합니다.

이 구문은 (느슨하게) 많은 Unix 셸에서 차용되었지만 셸 구문과 CMD.EXE 사이에 미묘한 차이가 있으므로주의해야합니다.

업데이트 : OP가 NUL내가 여기에 쓰고 있는 "파일"이라는 이름의 특수한 특성을 이해한다는 것을 알고 있지만 댓글 작성자는 이해하지 않았으므로 해당 측면에 대해 좀 더 자세히 설명하겠습니다.

MSDOS의 초기 릴리스로 돌아가서 특정 파일 이름은 파일 시스템 커널에 의해 선점되고 장치를 참조하는 데 사용되었습니다. 그 이름의 최초의 목록을 포함 NUL, PRN, CON, AUXCOM1를 통해 COM4. NULnull 장치입니다. 읽기 또는 쓰기를 위해 항상 열 수 있으며, 모든 양을 쓸 수 있으며 읽기는 항상 성공하지만 데이터를 반환하지 않습니다. 나머지는 병렬 프린터 포트, 콘솔 및 최대 4 개의 직렬 포트를 포함합니다. MSDOS 5부터는 예약 된 이름이 몇 개 더 있었지만 기본 규칙은 매우 잘 확립되어 있습니다.

Windows가 만들어 졌을 때 MSDOS 커널 위에 상당히 얇은 응용 프로그램 전환 계층으로 시작되었으므로 동일한 파일 이름 제한이 적용되었습니다. 윈도우 NT는 그 자체에 진정한 운영체제로 만들 때, 이름을 좋아 NUL하고 COM1너무 널리 제거를 허용하는 작업을 가정했다. 그러나 새로운 장치가 항상 실제 파일 이름의 향후 사용자를 차단하는 이름을 갖게된다는 생각은 분명히 불합리합니다.

Windows NT 및 이후의 모든 버전 (2K, XP, 7 및 현재 8)은 모두 커널 코드에서 훨씬 더 정교한 NT 네임 스페이스 를 사용하고 신중하게 구성되고 이식성이 뛰어난 사용자 공간 코드를 사용합니다. 해당 이름 공간에서 장치 드라이버는 \Device폴더를 통해 볼 수 있습니다 . 필요한 이전 버전과의 호환성을 지원하기 위해 \DosDevices모든 파일 시스템 폴더에 예약 된 파일 이름 목록을 구현하는 폴더를 사용하는 특수 메커니즘이 있습니다. 사용자 코드는 일반적인 Win32 API 아래의 API 계층을 사용하여이 내부 이름 공간을 탐색 할 수 있습니다. 커널 네임 스페이스를 탐색하기위한 좋은 도구 는 Microsoft의 SysInternals 그룹의 WinObj 입니다.

Windows에서 파일 (및 장치)의 법적 이름을 둘러싼 규칙에 대한 전체 설명을 보려면 MSDN의이 페이지가 유익하고 벅차게 될 것입니다. 규칙은 당연한 것보다 훨씬 더 복잡하며 "법적인 정규화 된 경로 이름이 얼마나 긴가?"와 같은 간단한 질문에 실제로 대답하는 것은 불가능합니다.


5
답변 해 주셔서 감사합니다. 무엇보다도 설명해 주셔서 감사합니다.
JosephStyons

권장 사항 : taskkill /im "test.exe" /f >%temp%\nul 2>&1 & del %temp%\nul. 이렇게하면 빈 null 파일이 로컬 디렉터리에 배치되는 것을 방지 할 수 있습니다
Samy Bencherif

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"작업을 종료합니다. 로 리디렉션 stderr합니다 stdout. 그런 다음로 리디렉션 stdout합니다 nul.

@중지

Press any key to continue . . . 누군가 키를 누를 때까지 일시 중지 메시지를 표시합니다 .

참고 : @기호는 각 명령에 대한 프롬프트를 숨기고 있습니다. 이 방법으로 최대 8 바이트를 저장할 수 있습니다.

스크립트의 가장 짧은 버전은 다음과 같을 수 있습니다.
@taskkill/f /im test.exe >nul 2>&1&pause
&문자는 처음에는 리디렉션에 사용되고 두 번째에는 명령을 구분하는 데 사용됩니다.
@줄에 두 번 문자가 필요하지 않습니다. 이 코드는 게시 한 코드가 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.
weir
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.