ít file1 file2 | mèo - tại sao nó hoạt động?


21

Khi tôi sử dụng, less file1 file2tôi nhận được cả hai tệp được hiển thị trong "trình xem bộ đệm ít hơn", nhưng less file1 file2 | catin nội dung của cả hai tệp được thêm vào thiết bị xuất chuẩn. Làm thế nào ít biết nếu nó sẽ hiển thị "trình xem bộ đệm ít hơn" hoặc tạo đầu ra cho thiết bị xuất chuẩn cho lệnh tiếp theo? Cơ chế nào được sử dụng để làm điều này?

Câu trả lời:


30

lessin văn bản đến thiết bị xuất chuẩn. đi ra

  • đến một thiết bị đầu cuối (/ dev / tty?) và mở trình xem bộ đệm mặc định
  • thông qua một đường ống khi dẫn nó đến một chương trình khác bằng cách sử dụng | ( less text | cut -d: -f1)
  • đến một tệp khi chuyển hướng nó với> ( less text > tmp)

Có một hàm C được gọi là "isa tty " để kiểm tra xem đầu ra có đi đến tty không (dưới 4,81, main.c, dòng 112). Nếu vậy, nó sử dụng trình xem bộ đệm nếu không nó hoạt động như thế nào cat.

Trong bash bạn có thể sử dụng thử nghiệm (xem man test)

  • -t mô tả tệp FD FD được mở trên thiết bị đầu cuối
  • -p FILE tồn tại và là một ống có tên

Thí dụ:

[[ -t 1 ]] && \
    echo 'STDOUT is attached to TTY'

[[ -p /dev/stdout ]] && \
    echo 'STDOUT is attached to a pipe'

[[ ! -t 1 && ! -p /dev/stdout ]] && \
    echo 'STDOUT is attached to a redirection'

1
@tfh Nếu STDOUT không được gắn vào đường ống hoặc chuyển hướng, thì đúng là họ không in rằng STDOUT được gắn vào đường ống hoặc chuyển hướng. Đặt cả ba trong một kịch bản. Gọi bash script.sh, bash script.sh | cat, bash script.sh > file, và xem những gì bạn nhận được đầu ra.
hvd

1
stdoutkhông phải là một cái gì đó có thể được "ghi vào một tập tin". Đó là một cái gì đó bạn write() muốn . lesskhông phải làm bất cứ điều gì khác nhau tùy thuộc vào việc đầu ra của nó là một tệp, đường ống, ổ cắm hoặc thiết bị khối hay bất cứ thứ gì. Nó chỉ quan trọng rằng nó không phải là một tty, vì vậy nó chỉ hành xử như thế cat. (Tôi cho rằng bạn biết điều này và chỉ chọn những từ sai để giải thích nó, nhưng tôi nghĩ tôi sẽ chỉ ra điều này cho những người đọc khác).
Peter Cordes

Vì vậy, ý bạn là nhiệm vụ ít phải cư xử như con mèo trong câu hỏi cụ thể của tôi - hay nói chung hơn: hành xử như lệnh tiếp theo trong một đường ống dẫn. Từ những gì tôi hiểu, tôi không thể cho rằng hành vi tương tự cũng được thực hiện trong một công cụ khác.
tfh

@tfh: Không, lesskhông "tìm ra" cattiếp theo. Nó chỉ hành xử như catbất kể nó là gì tiếp theo, nếu nó không phải là một tty.
Peter Cordes

@MichaelD.: Cảm ơn, đã sửa câu trả lời của tôi. Tôi chỉ đoán rằng lesssẽ đi trước và sử dụng một TCGETS để có được kích thước thiết bị đầu cuối hoặc phát hiện ra rằng đó không phải là một tty, nhưng rõ ràng tôi đã đoán sai.
Peter Cordes

6

lesskiểm tra xem nó stdoutcó phải là thiết bị đầu cuối không và hoạt động như thế catnào khi không (sao chép stdin sang thiết bị xuất chuẩn cho đến khi EOF).

Tính năng này cho phép bạn viết các tập lệnh hoặc chương trình luôn gửi đầu ra của chúng (ví dụ như --helpđầu ra) lesstrong khi vẫn cho phép chuyển hướng dễ dàng đến một tệp. Nó sẽ hút nếu some_command --fullhelp > help.txtvẫn chờ thanh không gian trên stdin đến trang thông qua văn bản, hoặc một cái gì đó. Một số lệnh (ví dụ man) kiểm tra xem đầu ra của chính chúng để quyết định có gửi đầu ra của chúng thông qua máy nhắn tin hay không. Nếu bạn chạy man ls > ls.txt, nó không bao giờ gọi bạn $PAGER.

lessHành vi giống như con mèo rất tiện lợi nếu bạn quên chỉnh sửa nó từ một lớp lót khi thêm nhiều giai đoạn vào đường ống.


lesscần phải tìm ra kích thước thiết bị đầu cuối (kích thước màn hình, để biết có bao nhiêu dòng hiển thị cùng một lúc). Việc ioctl(2)sử dụng nó stdoutsẽ trả về ENOTTY trên một thiết bị đầu cuối, vì vậy dù sao nó cũng không thể tránh xử lý trường hợp không phải thiết bị đầu cuối. lessthực sự sử dụng isatty(3)trước khi kiểm tra kích thước thiết bị đầu cuối, nhưng isattyhoạt động bằng cách thử ioctl chỉ tty và kiểm tra thiếu lỗi.

Ngay cả một máy nhắn tin đơn giản như more(1)(ít nhất là phiên bản linux-linux) cũng có tính năng này, bởi vì đó có lẽ là hành vi lành mạnh đơn giản nhất để thực hiện cho trường hợp đó.


Lưu ý rằng khi bạn đặt một cái gì đó vào less (ví dụ grep foo bar.txt | less), nó phải mở /dev/ttycho đầu vào bàn phím. (Bạn có thể thấy nó làm điều này với echo foo | strace less).

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.