`Cat <> file` hoạt động như thế nào?


42

cat < filein nội dung của tập tin vào thiết bị xuất chuẩn.

cat > fileđọc stdin cho đến khi Ctrl+ Dđược phát hiện và văn bản đầu vào được ghi vào tệp .

cat <> file, ít nhất là trong phiên bản Bash của tôi, in nội dung tệp một cách vui vẻ (không có lỗi), nhưng không sửa đổi tệp cũng như không cập nhật dấu thời gian sửa đổi.

Làm thế nào để tiêu chuẩn Bash biện minh cho việc dường như bị bỏ qua >trong tuyên bố thứ ba - và quan trọng hơn là nó có làm gì không?

Câu trả lời:


47

Bash sử dụng <>để tạo một mô tả tệp đọc-ghi :

Toán tử chuyển hướng

[n]<>word

làm cho tệp có tên là mở rộng từ được mở cho cả đọc và ghi trên mô tả tệp n hoặc trên mô tả tệp 0 nếu n không được chỉ định. Nếu tập tin không tồn tại, nó được tạo ra.

cat <> filemở fileđọc-ghi và liên kết nó với mô tả 0 (đầu vào tiêu chuẩn). Về cơ bản, nó tương đương < filevới bất kỳ chương trình được viết hợp lý nào, vì không ai có thể thử viết vào đầu vào tiêu chuẩn thông thường, nhưng nếu có thì nó sẽ có thể.

Bạn có thể viết một chương trình C đơn giản để kiểm tra trực tiếp - write(0, "hello", 6)sẽ ghi hellovào filethông qua đầu vào tiêu chuẩn.

<>cũng nên hoạt động trong bất kỳ hệ vỏ tương thích POSIX nào khác có cùng tác dụng.


1
Viết ... cho stdin? ... Có trường hợp sử dụng hợp lệ nào cho việc này không?
Qix

3
Trái tay, tôi không thể nghĩ ra cái nào tốt cả. Đưa ra một mô tả rõ ràng ( 4<>file) là hữu ích và tôi cho rằng 0 là một mặc định tốt như bất kỳ khi nào bạn bỏ nó. Đọc từ thiết bị xuất chuẩn không tốt hơn.
Michael Homer

5
<>cũng hữu ích trên một số hệ thống (như Linux) để mở các ống có tên mà không chặn cho đến khi một quy trình khác mở ra để viết.
Stéphane Chazelas

1
@Qix: Viết tốt (0, "Mật khẩu:", 10) là một cách hay để nhắc mật khẩu nếu bạn có ý định nhắc bất cứ điều gì giống như một tty. Tôi đã từng thấy nó chỉ trên stderr nhưng không có lý do cụ thể nào là kỹ thuật tương tự không hoạt động trên stdin.
Joshua

3
@Qix - từ Cơ sở lý luận POSIX - Nhà <>điều hành có thể hữu ích trong việc viết một ứng dụng hoạt động với một số thiết bị đầu cuối và đôi khi muốn khởi động hệ vỏ. Lớp vỏ đó sẽ không thể chạy các ứng dụng chạy từ thiết bị đầu cuối điều khiển thông thường trừ khi nó có thể sử dụng <>... chẳng hạn như ... máy nhắn tin more, đọc từ lỗi tiêu chuẩn để nhận lệnh của nó, vì vậy đầu vào tiêu chuẩn và đầu ra tiêu chuẩn đều có sẵn cho việc sử dụng thông thường của họ. cat food | more - >/dev/tty03 2<>/dev/tty03
mikeerv

38

<> filemở tệp (trên mô tả tệp 0 (stdin) theo mặc định, như <) trong chế độ đọc + ghi mà không cắt bớttạo tệp nếu nó không tồn tại trước đó .

Điều đó tương ứng với các O_RDWR|O_CREATcờ được truyền cho open()cuộc gọi hệ thống. Ngược lại <O_RDONLY>O_WRONLY|O_CREAT|O_TRUNC>> O_WRONLY|O_CREAT|O_APPEND.

Có stdin có thể ghi thường không hữu ích vì các ứng dụng thường không ghi vào stdin của chúng. Các ứng dụng thường không mong đợi để đọc viết trên một mô tả tệp mà họ nhận được khi khởi động; họ thường đọc từ stdin (hoặc một bộ mô tả tệp mà họ tự mở) và viết cho thiết bị xuất chuẩn hoặc thiết bị xuất chuẩn (hoặc một bộ mô tả tệp mà họ tự mở).

<> có thể có công dụng của nó:

  • Bạn có thể thích cat <> filehơn cat < filenếu bạn không muốn lệnh thất bại nếu filekhông tồn tại, nhưng filethay vào đó , một khoảng trống được tạo.
  • Khía cạnh cắt ngắn <>làm cho nó hữu ích để ghi đè lên các tệp tại chỗ. Tuy nhiên, trong trường hợp đó, bạn thường không sử dụng nó trên mô tả tệp 0:

    printf xxx 1<> file

    thay thế 3 byte đầu tiên filebằng xxx.

  • Trên một số hệ thống như Linux, <>trên một đường ống có tên (FIFO) sẽ mở đường ống có tên mà không chặn (không phải chờ một quá trình khác để mở đầu kia) và đảm bảo cấu trúc đường ống được tồn tại. Ví dụ:

    mkfifo pipe; sed 's/foo/bar/g' <> pipe

    sedxử lý dữ liệu đến từ bất kỳ số lượng quá trình khác ghi vào nó và không bao giờ nhìn thấy eof.


1
Lưu ý rằng trên AT & T ksh93, <>mặc định là 1<>(stdout) thay vì 0<>(stdin). Đây là lỗi tuân thủ POSIX mà tôi đã báo cáo và sẽ được khắc phục trong phiên bản tiếp theo. github.com/att/ast/issues/75 Nhưng cho đến khi các phiên bản ksh93 hiện tại không sử dụng, bạn phải bao gồm số mô tả tệp để sử dụng một cách hợp lý <>.
Martijn Dekker

@MartijnDekker, tôi biết, tôi là người nói với bạn về điều đó ngay từ đầu ;-). Lưu ý rằng nó chỉ dành cho ksh93t + (nơi hành vi thay đổi) trở lên.
Stéphane Chazelas

Các hệ thống không giống như Linux mkfifo fifo; exec 3<>fifosẽ chặn ở đâu?
Chú Billy
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.