Đầu tiên để cắt bỏ các câu trả lời tầm thường nhưng không thể áp dụng: Tôi không thể sử dụng cả mẹo find
+ xargs
cũng như các biến thể của nó (như find
với -exec
) vì tôi cần sử dụng một vài biểu thức như vậy cho mỗi cuộc gọi. Tôi sẽ trở lại điều này vào cuối.
Bây giờ để có một ví dụ tốt hơn, hãy xem xét:
$ find -L some/dir -name \*.abc | sort
some/dir/1.abc
some/dir/2.abc
some/dir/a space.abc
Làm thế nào để tôi vượt qua những điều đó như là đối số program
?
Chỉ làm điều đó không phải là lừa
$ ./program $(find -L some/dir -name \*.abc | sort)
thất bại vì program
nhận được các đối số sau:
[0]: ./program
[1]: some/dir/1.abc
[2]: some/dir/2.abc
[3]: some/dir/a
[4]: space.abc
Có thể thấy, đường dẫn với không gian đã được phân chia và program
coi đó là hai đối số khác nhau.
Trích dẫn cho đến khi nó hoạt động
Có vẻ như những người dùng mới làm quen như tôi, khi gặp phải những vấn đề như vậy, có xu hướng thêm các trích dẫn ngẫu nhiên cho đến khi cuối cùng nó hoạt động - chỉ ở đây, nó dường như không giúp ích gì cho
"$(…)"
$ ./program "$(find -L some/dir -name \*.abc | sort)"
[0]: ./program
[1]: some/dir/1.abc
some/dir/2.abc
some/dir/a space.abc
Vì các trích dẫn ngăn chia tách từ, tất cả các tệp được truyền dưới dạng một đối số.
Trích dẫn từng con đường
Một cách tiếp cận đầy hứa hẹn:
$ ./program $(find -L some/dir -name \*.abc -printf '"%p"\n' | sort)
[1]: "some/dir/1.abc"
[2]: "some/dir/2.abc"
[3]: "some/dir/a
[4]: space.abc"
Các trích dẫn là có, chắc chắn. Nhưng chúng không còn được giải thích. Họ chỉ là một phần của chuỗi. Vì vậy, không chỉ họ không ngăn chặn việc chia tách từ mà còn gây tranh cãi!
Thay đổi IFS
Sau đó, tôi đã thử chơi xung quanh với IFS
. Tôi muốn find
có -print0
và sort
với -z
anyway - để họ sẽ không có vấn đề trên "đường dây" bản thân. Vậy tại sao không buộc từ chia tách trên null
nhân vật và có tất cả?
$ ./program $(IFS=$'\0' find -L some/dir -name \*.abc -print0 | sort -z)
[0]: ./program
[1]: some/dir/1.abcsome/dir/2.abcsome/dir/a
[2]: space.abc
Vì vậy, nó vẫn phân chia trên không gian và không phân chia trên null
.
Tôi đã cố gắng đặt IFS
bài tập cả trong $(…)
(như hình trên) và trước đó ./program
. Ngoài ra tôi đã cố gắng cú pháp khác như \0
, \x0
, \x00
cả hai được trích dẫn với '
và "
cũng như có và không có $
. Không ai trong số họ dường như tạo ra bất kỳ sự khác biệt nào
Và ở đây tôi hết ý tưởng. Tôi đã thử thêm vài thứ nhưng tất cả dường như gặp vấn đề tương tự như được liệt kê.
Tôi có thể làm gì khác? Có thể làm được gì không?
Chắc chắn, tôi có thể program
chấp nhận các mẫu và tự tìm kiếm. Nhưng nó là rất nhiều công việc gấp đôi trong khi sửa nó thành một cú pháp cụ thể. (Điều gì về việc cung cấp các tệp bằng một grep
ví dụ?).
Ngoài ra tôi có thể program
chấp nhận một tập tin với một danh sách các đường dẫn. Sau đó, tôi có thể dễ dàng kết xuất find
biểu thức vào một số tệp tạm thời và chỉ cung cấp đường dẫn đến tệp đó. Điều này có thể được hỗ trợ dọc theo các đường dẫn trực tiếp để nếu người dùng chỉ có một đường dẫn đơn giản thì nó có thể được cung cấp mà không cần tệp trung gian. Nhưng điều này có vẻ không hay - người ta cần tạo thêm tệp và chăm sóc chúng, chưa kể đến việc thực hiện thêm. (Tuy nhiên, về mặt tích cực, nó có thể là một giải cứu cho các trường hợp trong đó số lượng tệp làm đối số bắt đầu gây ra sự cố với độ dài dòng lệnh
Cuối cùng, hãy để tôi nhắc bạn một lần nữa rằng các thủ thuật find
+ xargs
(và tương tự) sẽ không hoạt động trong trường hợp của tôi. Để mô tả đơn giản, tôi chỉ hiển thị một đối số. Nhưng trường hợp thực sự của tôi trông giống như thế này:
$ ABC_FILES=$(find -L some/dir -name \*.abc | sort)
$ XYZ_FILES=$(find -L other/dir -name \*.xyz | sort)
$ ./program --abc-files $ABC_FILES --xyz-files $XYZ_FILES
Vì vậy, thực hiện một xargs
tìm kiếm từ một tìm kiếm vẫn còn cho tôi cách đối phó với một tìm kiếm khác
mapfile
(hoặc từ đồng nghĩa của nóreadarray
). Nhưng nó làm việc!