Làm thế nào tôi có thể chặn tất cả đầu ra từ một lệnh bằng Bash?


296

Tôi có một đoạn script Bash chạy một chương trình với các tham số. Chương trình đó đưa ra một số trạng thái (làm điều này, làm điều đó ...). Không có lựa chọn nào cho chương trình này được yên tĩnh. Làm thế nào tôi có thể ngăn tập lệnh hiển thị bất cứ điều gì?

Tôi đang tìm kiếm một cái gì đó như "tiếng vang" của Windows .

Câu trả lời:


510

Sau đây sẽ gửi đầu ra tiêu chuẩn đến thiết bị null (bit bit).

scriptname >/dev/null

Và nếu bạn cũng muốn thông báo lỗi được gửi đến đó, hãy sử dụng một trong những (đầu tiên có thể không hoạt động trong tất cả các shell):

scriptname &>/dev/null
scriptname >/dev/null 2>&1
scriptname >/dev/null 2>/dev/null

Và, nếu bạn muốn ghi lại các tin nhắn, nhưng không nhìn thấy chúng, hãy thay thế /dev/nullbằng một tệp thực tế, chẳng hạn như:

scriptname &>scriptname.out

Để đầy đủ, trong Windows cmd.exe (trong đó "nul" tương đương với "/ dev / null"), đó là:

scriptname >nul 2>nul

8
Lưu ý rằng '&>' là đặc thù của bash (và có thể là vỏ C); Các shell Korn và Bourne yêu cầu 2> / dev / null hoặc 2> & 1 (để gửi stderr đến cùng một nơi với thiết bị xuất chuẩn). Trình bao Korn dường như diễn giải '&>' là "chạy các công cụ lên & trong nền, sau đó thực hiện chuyển hướng i / o trên một lệnh trống".
Jonathan Leffler

2
Lưu ý rằng một số lệnh ghi trực tiếp vào thiết bị đầu cuối thay vì đầu ra / lỗi tiêu chuẩn. Để kiểm tra, đặt echo foo > $(tty)tập lệnh và chạy ./test.sh &> /dev/null- Đầu ra vẫn được in đến thiết bị đầu cuối. Tất nhiên đây không phải là vấn đề nếu bạn đang viết một tập lệnh không sử dụng các lệnh như vậy.
l0b0

1
@ l0b0, có cách nào để làm cho tập lệnh (hoặc bất kỳ chương trình nào khác) khác biệt để tất cả đầu ra được chuyển hướng bất kể ví dụ của bạn không? Tôi biết màn hình và kịch bản có thể làm một cái gì đó như thế nhưng cả hai đều tinh xảo và thay đổi từ * nix đến * nix.
Brent

@yang /dev/nulltồn tại trong Cygwin, bạn không cần sử dụng nul.
dimo414

47

Cái gì đó như

script > /dev/null 2>&1

Điều này sẽ ngăn đầu ra tiêu chuẩn đầu ra lỗi, chuyển hướng cả hai đến /dev/null.


5
Cũng đạt được chỉ với &> nếu bạn muốn lưu một số thao tác gõ;)
andynormancx

1
Mặc dù tôi đang thêm lệnh này vào lệnh gs (GhostScript) của mình, nó vẫn in ra **** Cảnh báo: Tệp có dấu %% EOF bị hỏng hoặc rác sau %% EOF. Có lời khuyên nào không?
ZurabWeb

Điều này không chạy quy trình trên các hệ thống unix, tôi phải làm2>/dev/null
bắt đầu từ

13

Thử

: $(yourcommand)

: là viết tắt của "không làm gì".

$() chỉ là mệnh lệnh của bạn.


3
Rất thú vị nhưng có một hạn chế: mã trạng thái được trả về luôn luôn 0(thành công). Chúng ta hãy xem một ví dụ sử dụng lệnh falseluôn trả về 1(thất bại). Ví dụ ( echo foo | tee file ; false ) && echo barhiển thị foo. Sử dụng thủ thuật của bạn để ngăn chặn đầu ra : ( : $(echo foo | tee file ; false) ) && echo bar. Nhưng nó hiển thị barnghĩa là mã trạng thái trả về là 0(đây không phải là mã trạng thái được trả về từ false). Vui lòng cập nhật câu trả lời của bạn cung cấp giới hạn này. Chúc mừng
olibre

2
@olibre, còn gì DUMMY=$(yourcommand)? Nó không có giới hạn mà bạn đã đề cập. :)
semente 14/03/2016

3
@semente Perfect: Lệnh DUMMY=$( echo foo | tee file ; false ) && echo barkhông hiển thị gì cả. Và lệnh DUMMY=$( echo foo | tee file ; true ) && echo barhiển thị bar. Hãy cho tôi biết nếu bạn cung cấp câu trả lời để nâng cấp nó ;-) Chúc mừng
olibre

9

Một thay thế có thể phù hợp trong một số tình huống là gán kết quả của lệnh cho một biến:

$ DUMMY=$( grep root /etc/passwd 2>&1 )
$ echo $?
0
$ DUMMY=$( grep r00t /etc/passwd 2>&1 )
$ echo $?
1

Vì Bash và các trình thông dịch dòng lệnh POSIX khác không coi các phép gán biến là một lệnh, nên mã trả về của lệnh hiện tại được tuân thủ.

Lưu ý: phép gán với typesethoặc declaretừ khóa được coi là một lệnh, vì vậy mã trả về được đánh giá trong trường hợp là chính phép gán và không phải là lệnh được thực thi trong lớp vỏ phụ:

$ declare DUMMY=$( grep r00t /etc/passwd 2>&1 )
$ echo $?
0

6

Giống như bài đăng của andynormancx , hãy sử dụng bài đăng này (nếu bạn đang làm việc trong môi trường Unix):

scriptname > /dev/null

Hoặc bạn có thể sử dụng điều này (nếu bạn đang làm việc trong môi trường Windows):

scriptname > nul

1
Bạn thực sự có thể làm tốt hơn thế trong shell Windows. Nếu thay vào đó, bạn sử dụng "scriptname> nul" thì bạn thậm chí sẽ không có tệp để xóa, vì "nul" là tương đương với Windows / dev / null.
andynormancx

1
@andynormancx: Đó là điều tôi ghét về cách bố trí hệ thống tệp Windows. Nó "dự trữ" các tên tệp như NUL, COM1, LPT1, CON, v.v., bất kể bạn đang ở thư mục nào (ngay cả khi bạn đang ở trong một hệ thống tệp có thể có các tên tệp đó, như trong chia sẻ mạng).
dreamlax

Tôi không nghĩ rằng tôi thực sự đã sử dụng NUL kể từ DOS 5.x, đã có một hồi tưởng bất chợt khi tôi thấy câu trả lời này;)
andynormancx

Trong trường hợp bạn đã sử dụng > nultrên Windows với cygwin hoặc git bash và bây giờ bạn bị mắc kẹt với một nultệp không thể xóa, vui lòng thử câu trả lời này , nó hoạt động như một bùa mê.
Họa sĩ Daemon

4

Hãy xem ví dụ này từ Dự án Tài liệu Linux :

3.6 Mẫu: tệp stderr và stdout 2

Điều này sẽ đặt mọi đầu ra của một chương trình vào một tập tin. Điều này đôi khi phù hợp cho các mục cron, nếu bạn muốn một lệnh truyền trong im lặng tuyệt đối.

     rm -f $(find / -name core) &> /dev/null 

Điều đó nói rằng, bạn có thể sử dụng chuyển hướng đơn giản này:

/path/to/command &>/dev/null

1

Trong tập lệnh của bạn, bạn có thể thêm dòng sau vào các dòng mà bạn biết sẽ cung cấp đầu ra:

some_code 2>>/dev/null

Hoặc nếu không bạn cũng có thể thử

some_code >>/dev/null

1
không bao giờ thấy >> to / dev / null .. vì tò mò .. Tại sao bạn làm điều này?
Florian Berndl

Là nó triệt tiêu tất cả đầu ra?
Peter Mortensen

Tại sao nhân đôi ">" ( >>)?
Peter Mortensen
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.