Bỏ đầu ra dòng lệnh


118

Tôi có một tệp bó đơn giản như thế này:

dội lại

tác vụ / im "test.exe" / f> nul

tạm ngừng

Nếu "test.exe" không chạy, tôi nhận được thông báo này:

LRI: Không tìm thấy quá trình "test.exe".

Tại sao thông báo lỗi này được hiển thị, mặc dù tôi đã chuyển hướng đầu ra sang NUL?

Làm thế nào tôi có thể ngăn chặn đầu ra đó?

Câu trả lời:


212

Bởi vì thông báo lỗi thường đi đến stderrkhôngstdout .

Thay đổi lời mời này:

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

và tất cả sẽ tốt hơn

Điều đó hoạt động vì stdoutlà mô tả tệp 1, và stderrlà mô tả tệp 2 theo quy ước. (0 là stdin, tình cờ.) Bộ 2>&1mô tả tệp đầu ra sao chép 2 từ giá trị mới là 1, vừa được chuyển hướng đến thiết bị null.

Cú pháp này (lỏng lẻo) được mượn từ nhiều shell Unix, nhưng bạn phải cẩn thận vì có sự khác biệt tinh tế giữa cú pháp shell và CMD.EXE.

Cập nhật: Tôi biết OP hiểu bản chất đặc biệt của "tệp" có tên NULtôi đang viết ở đây, nhưng một người bình luận đã không và vì vậy hãy để tôi lạc đề với một chi tiết nhỏ hơn về khía cạnh đó.

Quay trở lại các bản phát hành sớm nhất của MSDOS, một số tên tệp nhất định đã được nhân hệ thống tệp ưu tiên và sử dụng để chỉ các thiết bị. Danh sách sớm nhất của những tên bao gồm NUL, PRN, CON, AUXCOM1thông qua COM4.NULlà thiết bị null. Nó luôn có thể được mở để đọc hoặc viết, bất kỳ số tiền nào cũng có thể được ghi trên đó và đọc luôn thành công nhưng không trả lại dữ liệu. Những cái khác bao gồm cổng máy in song song, bàn điều khiển và tối đa bốn cổng nối tiếp. Kể từ MSDOS 5, có một vài cái tên được bảo lưu nhiều hơn, nhưng quy ước cơ bản đã được thiết lập rất tốt.

Khi Windows được tạo, nó bắt đầu cuộc sống như một lớp chuyển đổi ứng dụng khá mỏng bên trên hạt nhân MSDOS, và do đó có cùng các hạn chế tên tệp. Khi Windows NT được tạo ra như một hệ điều hành thực sự theo đúng nghĩa của nó, các tên như NULCOM1được cho là quá rộng rãi để hoạt động để cho phép loại bỏ chúng. Tuy nhiên, ý tưởng rằng các thiết bị mới sẽ luôn nhận được các tên sẽ chặn người dùng tương lai của các tên đó cho các tệp thực tế rõ ràng là không hợp lý.

Windows NT và tất cả các phiên bản tiếp theo (2K, XP, 7 và bây giờ 8) đều sử dụng Không gian tên NT phức tạp hơn nhiều từ mã hạt nhân và mã không gian người dùng được xây dựng cẩn thận và không di động. Trong không gian tên đó, trình điều khiển thiết bị được hiển thị thông qua \Devicethư mục. Để hỗ trợ khả năng tương thích ngược yêu cầu, có một cơ chế đặc biệt sử dụng \DosDevicesthư mục thực hiện danh sách các tên tệp dành riêng trong bất kỳ thư mục hệ thống tệp nào. Mã người dùng có thể duyệt không gian tên nội bộ này bằng cách sử dụng lớp API bên dưới API Win32 thông thường; một công cụ tốt để khám phá không gian tên kernel là WinObj từ nhóm SysIternals tại Microsoft.

Để có một mô tả đầy đủ về các quy tắc xung quanh tên hợp pháp của các tệp (và thiết bị) trong Windows, trang này tại MSDN sẽ vừa mang tính thông tin vừa gây nản lòng. Các quy tắc là một nhiều hơn phức tạp hơn những gì họ nên được, và nó thực sự là không thể trả lời một số câu hỏi đơn giản như "là hợp pháp tên đường dẫn đầy đủ nhất? Bao lâu".


5
Cảm ơn câu trả lời, và hầu hết tất cả cho lời giải thích.
JosephStyons

Một khuyến nghị : taskkill /im "test.exe" /f >%temp%\nul 2>&1 & del %temp%\nul. Điều này sẽ ngăn không cho một tập tin null trống vào thư mục cục bộ
Samy Bencherif

11
@SamyBencherif, NULlà tên tệp dành riêng và ánh xạ tới thiết bị NUL. Bạn không thể tạo một tập tin thực tế có tên NULtrong bất kỳ thư mục.
RBerteig

7

Sử dụng tập lệnh này thay thế:

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

Những gì 2>&1phần thực sự làm, là nó chuyển hướng stderrđầu ra stdout. Tôi sẽ giải thích nó tốt hơn dưới đây:

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

Giết nhiệm vụ "test.exe". Chuyển hướng stderrđến stdout. Sau đó, chuyển hướng stdoutđến nul.

@tạm ngừng

Hiển thị thông báo tạm dừng Press any key to continue . . . cho đến khi ai đó nhấn phím.

LƯU Ý: @ Biểu tượng đang ẩn dấu nhắc cho mỗi lệnh. Bạn có thể tiết kiệm tới 8 byte theo cách này.

Phiên bản ngắn nhất của tập lệnh của bạn có thể là:
@taskkill/f /im test.exe >nul 2>&1&pause
&tự được sử dụng để chuyển hướng lần đầu tiên và để tách các lệnh lần thứ hai.
Một @nhân vật không cần thiết hai lần trong một dòng. Mã này chỉ có 40 byte, mặc dù mã bạn đã đăng là 49 byte! Tôi thực sự đã lưu 9 byte. Đối với một mã sạch hơn nhìn ở trên.


Có tôi biết một nửa bài viết thực sự là làm thế nào để rút ngắn mã của bạn.
EKons

3

mysqldump không hoạt động với: > nul 2> & 1
Thay vào đó sử dụng: 2> nul
Điều này ngăn chặn thông báo stderr: "Cảnh báo: Sử dụng mật khẩu trên giao diện dòng lệnh có thể không an toàn"


0

Bạn cũng có thể làm điều này thay thế:

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

Mặc dù bối cảnh của câu hỏi là tập lệnh bó, tôi thấy rằng trong PowerShell, cú pháp trên không thành công với " out-file: FileStream được yêu cầu mở một thiết bị không phải là tệp. Để hỗ trợ cho các thiết bị như 'com1:' hoặc 'lpt1: ', Gọi CreatFile, sau đó sử dụng các hàm tạo FileStream có xử lý HĐH làm IntPtr. "Giải pháp là thay thế > nulbằng >$null.
đập
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.