Làm thế nào để đầu ra lệnh ống cho các lệnh khác?


83

Thí dụ:

ls | echoin không có gì (một dòng trống, thực sự). Tôi hy vọng nó sẽ in một danh sách các tập tin.

ls | grep 'foo'mặt khác, hoạt động như mong đợi (in các tệp có 'foo' trong tên của họ).

Những gì tôi làm trong những tình huống này là một cái gì đó như: ls | while read OUT; do echo $OUT; donenhưng điều này khá cồng kềnh.

Tại sao đường ống làm việc với một số lệnh, nhưng không phải với các lệnh khác? Làm thế nào tôi có thể phá vỡ vấn đề này?


2
Bạn mong đợi ls | echolàm gì? Tại sao không đơn giản là chạy ls?
theomega

12
Tôi đã sử dụng ví dụ đơn giản nhất minh họa quan điểm của tôi. Tôi thực sự đã gặp phải vấn đề này khi tôi đang cố gắng tạo một lớp lót có thể hiển thị các đối tượng git trong kho đối tượng và kiểu của chúng. Vì vậy, tôi đã chuyển ID của đối tượng git cat-file, nhưng nó không hoạt động. Rõ ràng, echo có hành vi tương tự, vì vậy tôi đã sử dụng nó làm ví dụ.
Mihai Rotaru

cũng nhìn vào lệnh -n cho xargs, nó cho biết có bao nhiêu đối số để đưa vào tiểu ban. `... | xargs -n1 git cat-file`
Rich Homolka

Câu trả lời:


118

Có một sự khác biệt giữa các đối số dòng lệnh và đầu vào tiêu chuẩn. Một đường ống sẽ kết nối đầu ra tiêu chuẩn của một quá trình với đầu vào tiêu chuẩn của một quá trình khác. Vì thế

ls | echo

Kết nối đầu ra tiêu chuẩn của ls với đầu vào tiêu chuẩn của tiếng vang. Khỏe phải không? Chà, echo bỏ qua đầu vào tiêu chuẩn và sẽ kết xuất các đối số dòng lệnh của nó - không có trong trường hợp này - thiết bị xuất chuẩn của chính nó. Đầu ra: không có gì cả.

Có một vài giải pháp trong trường hợp này. Một là sử dụng một lệnh đọc stdin và dumps để stdout, chẳng hạn như cat.

ls | cat

Sẽ 'làm việc', tùy thuộc vào định nghĩa công việc của bạn là gì.

Nhưng những gì về trường hợp chung. Những gì bạn thực sự muốn là chuyển đổi thiết bị xuất chuẩn của một lệnh thành dòng lệnh args của một lệnh khác. Như những người khác đã nói, xargslà công cụ trợ giúp chính tắc trong trường hợp này, đọc dòng lệnh của nó lập luận cho một lệnh từ stdin của nó và xây dựng các lệnh để chạy.

ls | xargs echo

Bạn cũng có thể chuyển đổi một số, sử dụng lệnh thay thế $()

echo $(ls)

Cũng sẽ làm những gì bạn muốn.

Cả hai công cụ này đều khá cốt lõi để tạo kịch bản shell, bạn nên tìm hiểu cả hai.

Để đầy đủ, như bạn chỉ ra trong câu hỏi, cách cơ bản khác để chuyển stdin thành dòng lệnh args là readlệnh dựng sẵn của shell . Nó chuyển đổi "từ" (các từ được xác định bởi IFSbiến) thành biến tạm thời, mà bạn có thể sử dụng trong bất kỳ lệnh chạy nào.


1
Một câu trả lời rất hữu ích, cảm ơn bạn! Tôi hiện đang học bash và tôi đã thấy cả xargs và ký hiệu $ (*) trước đây, nhưng không chú ý đến chúng. Bây giờ tôi mới biết họ quan trọng như thế nào, và chắc chắn sẽ xem xét chúng.
Mihai Rotaru

1
xargs có thể là những gì OP đang tìm kiếm.
Iktys

19

ls | echochỉ in một dòng trống vì echođọc không có đầu vào; lệnh cuối cùng của đường ống thực sự echolà không in gì ngoài một dòng trống.

Nói chung là:

a | b

đảm bảo rằng đầu ra atrở thành đầu vào của b. Tôi đề nghị bạn đọc Pipelinesphần của man bash.


Nếu bạn thực sự muốn sử dụng lsechocùng nhau đây là một số ví dụ (khá vô dụng):

ls | xargs -L 1 echo
echo `ls`
for i in `ls` ; do echo $i ; done

11

Nếu bạn muốn echonhững lsthử lệnh:

ls | xargs echo

Điều này sẽ gọi echovới đầu ra của ls.


3
Hoặc ls | xargs -I {} echo {}nếu bạn muốn nó được gọi riêng cho từng dòng
Alex Abdugafarov

3

Tại sao không sử dụng đơn giản:

echo `ls`

Hoặc an toàn hơn nhiều:

echo "`ls -lrt`"

4
Hoặc thậm chí chỉ echo *.
Kazark
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.