Bash: Làm thế nào để đọc một dòng tại một thời điểm từ đầu ra của một lệnh?


49

Tôi đang cố gắng đọc đầu ra của một lệnh trong bash bằng cách sử dụng a while loop.

while read -r line
do
    echo "$line"
done <<< $(find . -type f)

Đầu ra tôi nhận được

ranveer@ranveer:~/tmp$ bash test.sh
./test.py ./test1.py ./out1 ./test.sh ./out ./out2 ./hello
ranveer@ranveer:~/tmp$ 

Sau này tôi đã thử

$(find . -type f) | 
while read -r line
do
    echo "$line"
done 

nhưng nó đã tạo ra một lỗi test.sh: line 5: ./test.py: Permission denied.

Vì vậy, làm thế nào để tôi đọc từng dòng một bởi vì tôi nghĩ hiện tại nó đang nhét toàn bộ dòng này cùng một lúc.

Yêu cầu đầu ra:

./test.py
./test1.py
./out1
./test.sh
./out
./out2
./hello

3
Tôi đề nghị đọc Bash FAQ 01 - rất nhiều thông tin và lời khuyên hữu ích về bẫy cần tránh.
jw013

Về while readphần, xem Hiểu IFS và các câu hỏi được liên kết ở đó.
Gilles 'SO- ngừng trở nên xấu xa'

Câu trả lời:


54

Có một sai lầm, bạn < <(command)không cần<<<$(command)

< <( )là một thay thế quy trình , $()là một thay thế lệnh<<<là một chuỗi ở đây .


2
@RanRag Ngừng cố gắng đưa $( )mọi thứ xung quanh! Đó là cú pháp để thay thế lệnh , đó chỉ là một cách để sử dụng đầu ra lệnh. Các ống và quá trình thay thế và các chuỗi ở đây là các chuỗi khác, và tất cả chúng đều có cú pháp khác nhau, một cách tự nhiên. Bạn không nên phân tích tên tệp bằng mọi cách trừ khi bạn thực sự biết bạn đang làm gì.
jw013

Cảm ơn nó đã làm việc sẽ đọc thêm về Process Substitution.
RanRag

@ jw013: Tôi là người mới bắt đầu bash. Trong tương lai sẽ giữ đề nghị của bạn trong tâm trí của tôi.
RanRag

13

Lưu ý rằng không có gì ngăn tên tệp chứa các ký tự dòng mới. Cách chính tắc để chạy một lệnh cho mỗi tệp được tìm thấy bởi find là.

find . -type f -exec cmd {} \;

Và nếu bạn muốn mọi thứ được thực hiện trong bash:

find . -type f -exec bash -c '
  for file do
    something with "$file"
  done' bash {} +

Ngoài ra, cách chính tắc để gọi lệnh "đọc" trong các tập lệnh (nếu bạn không muốn nó xử lý thêm vào đầu vào) là:

IFS= read -r var

-rlà dừng readviệc xử lý các ký tự dấu gạch chéo đặc biệt (như một ký tự thoát cho dấu phân cách và dòng mới), và IFS = để đặt danh sách các dấu phân cách thành chuỗi trống cho read(nếu không, nếu có bất kỳ ký tự khoảng trắng nào trong danh sách đó, chúng sẽ bị xóa khỏi bắt đầu và kết thúc đầu vào).

Sử dụng các vòng lặp trong shell thường là một ý tưởng tồi (không phải cách mọi thứ được thực hiện trong shell mà bạn tạo ra một số công cụ làm việc chung và đồng thời cho một nhiệm vụ thay vì chạy một hoặc nhiều công cụ theo trình tự hàng trăm lần).

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.