Chính xác thì <() trong bash (và = () trong zsh) là gì?


36

Tôi khá dễ thương với bash, nhưng gần đây tôi đã thay thế tôi không biết.

Chính xác là gì <(<command>)trong bash? Làm thế nào để nó so sánh với =(<command>)trong zsh?

Tôi hiểu rằng điều này có liên quan đến các mô tả tập tin mặc định. Trong máy tính của tôi

echo <()

trả về /proc/self/fd/11, mà tôi phát hiện ra là một bản sao của tập lệnh STDOUT, nhưng điều này vẫn có vẻ khá khó hiểu với tôi.

Câu trả lời:


51

Điều này được gọi là quá trình thay thế.

Các <(list)cú pháp được hỗ trợ bởi cả hai, bashzsh. Nó cung cấp một cách để chuyển đầu ra của một lệnh ( list) sang một lệnh khác khi không thể sử dụng pipe ( |). Ví dụ: khi một lệnh không hỗ trợ đầu vào từ STDINhoặc bạn cần đầu ra của nhiều lệnh:

diff <(ls dirA) <(ls dirB)

<(list)kết nối đầu ra của listmột tệp trong /dev/fd, nếu được hệ thống hỗ trợ, nếu không thì sử dụng một ống có tên (FIFO) (cũng phụ thuộc vào sự hỗ trợ của hệ thống; không có hướng dẫn nào nói điều gì xảy ra nếu cả hai cơ chế không được hỗ trợ, có lẽ nó sẽ hủy bỏ một lỗi). Tên của tệp sau đó được truyền dưới dạng đối số trên dòng lệnh.


zshNgoài ra hỗ trợ =(list)thay thế càng tốt cho <(list). Với =(list)một tệp tạm thời được sử dụng thay vì tệp trong /dev/fdhoặc một bộ xếp hình. Nó có thể được sử dụng để thay thế <(list)nếu chương trình cần lseek ở đầu ra.

Theo hướng dẫn ZSH , cũng có thể có các vấn đề khác về cách thức <(list)hoạt động:

Biểu =mẫu này rất hữu ích vì cả hai /dev/fdvà việc thực hiện đường ống có tên <(...)đều có nhược điểm. Trong trường hợp trước, một số chương trình có thể tự động đóng bộ mô tả tệp được đề cập trước khi kiểm tra tệp trên dòng lệnh, đặc biệt nếu điều này là cần thiết vì lý do bảo mật như khi chương trình đang chạy setuid. Trong trường hợp thứ hai, nếu chương trình không thực sự mở tệp, lớp con cố gắng đọc hoặc ghi vào đường ống sẽ (trong một triển khai điển hình, các hệ điều hành khác nhau có thể có hành vi khác nhau) mãi mãi và phải bị giết rõ ràng . Trong cả hai trường hợp, shell thực sự cung cấp thông tin bằng cách sử dụng một đường ống, do đó các chương trình dự kiến ​​sẽ lseek (xem trang man lseek(2)) trên tệp sẽ không hoạt động.


Điều này giúp tôi tìm ra lý do tại sao MacOS pfctl -f <(echo "pf rules")sẽ nói mô tả tệp xấu. sử dụng zsh và = (echo "pf rule") thay vào đó hoạt động.
johnnyB

9

Lưu ý, đây là một câu trả lời bash, không phải zsh.

Có những trường hợp trong bash mà bạn không thể sử dụng đường ống:

some_command | some_other_command

bởi vì các đường ống giới thiệu các lớp con cho từng thành phần của đường ống, khi lối thoát con thoát ra, mọi tác dụng phụ mà bạn đang dựa vào sẽ biến mất. Ví dụ, ví dụ giả định này:

cat file | while read line; do ((count++)); done
echo $count

sẽ hiển thị một dòng trống, bởi vì $countbiến không tồn tại trong shell hiện tại.

Việc thay thế quy trình bash cho phép bạn tránh câu hỏi hóc búa này bằng cách cho phép bạn đọc từ đầu ra "some_command" giống như bạn làm từ một tệp

while read line; do ((count++)); done < <(cat file)
# ....................................1.2
echo $count   # the variable *does* exist in the current shell

(1) là một chuyển hướng đầu vào bình thường. (2) là bắt đầu của <()cú pháp thay thế quá trình.


2
= (cmdlist) trong zsh có hiệu ứng gần như tương tự <(cmdlist) trong bash nhưng nó tạo (và xóa khi sẵn sàng) một tệp tạm thời với đầu ra của cmdlist để chuyển hướng. Điều này là tốt khi tìm kiếm có khả năng được thực hiện trong chương trình. <(cmdlist) cũng được biết đến bởi zsh.
Gombai Sándor
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.