Có vẻ như cách thức kinh điển để làm điều này bash
là một cái gì đó giống như
unset args
while IFS= read -r line; do
args+=("$line")
done < file
cmd "${args[@]}"
hoặc, nếu phiên bản bash của bạn có mapfile
:
mapfile -t args < filename
cmd "${args[@]}"
Sự khác biệt duy nhất tôi có thể tìm thấy giữa mapfile và vòng lặp while-đọc so với một-liner
(set -f; IFS=$'\n'; cmd $(<file))
là cái trước sẽ chuyển đổi một dòng trống thành một đối số trống, trong khi một dòng sẽ bỏ qua một dòng trống. Trong trường hợp này, hành vi một lớp là những gì tôi thích hơn, vì vậy, gấp đôi số tiền thưởng cho nó là nhỏ gọn.
Tôi sẽ sử dụng IFS=$'\n' cmd $(<file)
nhưng nó không hoạt động, bởi vì $(<file)
được giải thích để tạo thành dòng lệnh trước khi IFS=$'\n'
có hiệu lực.
Mặc dù nó không hoạt động trong trường hợp của tôi, nhưng bây giờ tôi đã học được rằng rất nhiều công cụ hỗ trợ chấm dứt các dòng null (\000)
thay vì newline (\n)
điều đó giúp cho việc này dễ dàng hơn khi xử lý, ví dụ như tên tệp, là nguồn phổ biến của các tình huống này :
find / -name '*.config' -print0 | xargs -0 md5
cung cấp danh sách các tên tệp đủ điều kiện dưới dạng đối số cho md5 mà không có bất kỳ nội dung hoặc nội suy hoặc bất cứ điều gì. Điều đó dẫn đến giải pháp không tích hợp
tr "\n" "\000" <file | xargs -0 cmd
mặc dù điều này cũng vậy, bỏ qua các dòng trống, mặc dù nó có các dòng chỉ có khoảng trắng.