Khi nào sẽ tìm thấy. -exec HÀNH {} + `thực thi LỆNH nhiều lần?


8

Nếu tôi làm

find . -exec echo {} +

nó in tất cả các đường dẫn trong một dòng, tức là lệnh chỉ echođược thực thi một lần.

Tuy nhiên, theo man find,

-exec command {} +
    ... the number of invocations of the command will 
be much  less  than  the  number  of matched files. ...

Có vẻ như trong một số trường hợp, lệnh sẽ được thực thi nhiều lần. Tôi có đúng không Hãy làm gương

Câu trả lời:


7

POSIX được xác định find -exec Utility_name [argument ...] {} + as:

Phần cuối của biểu thức chính sẽ được chấm câu bằng dấu chấm phẩy> hoặc bằng dấu <cộng>. Chỉ <dấu cộng> ngay sau một đối số chỉ chứa hai ký tự "{}" sẽ chấm dứt kết thúc của biểu thức chính. Việc sử dụng <dấu cộng> khác sẽ không được coi là đặc biệt. Nếu biểu thức chính bị ngắt quãng bởi một <dấu chấm phẩy>, tiện ích utility_name được gọi một lần cho mỗi tên đường dẫn và chính tổ chức thẩm định là đúng nếu các tiện ích trả về một giá trị không như trạng thái thoát. Một utility_name hoặc lập luận chỉ chứa hai chữ "{}" sẽ được thay thế bằng tên đường dẫn hiện hành. Nếu một tiện ích hoặc tên đối sốchuỗi chứa hai ký tự "{}", nhưng không chỉ hai ký tự "{}", nó được xác định theo thực thi cho dù tìm thay thế hai ký tự đó hoặc sử dụng chuỗi mà không thay đổi.

Nếu biểu thức chính được đánh dấu bằng dấu <cộng>, thì biểu thức chính sẽ luôn luôn được đánh giá là đúng và các tên đường dẫn được đánh giá chính sẽ được tổng hợp thành các tập hợp. Utility_name tiện ích sẽ được gọi một lần cho mỗi bộ tên đường dẫn tổng hợp. Mỗi lệnh gọi sẽ bắt đầu sau khi tên đường dẫn cuối cùng trong tập hợp được tổng hợp và sẽ được hoàn thành trước khi thoát khỏi tiện ích tìm kiếm và trước khi tên đường dẫn đầu tiên trong tập tiếp theo (nếu có) được tổng hợp cho chính này, nhưng nếu không thì sẽ không xác định được liệu lời gọi đó xảy ra trước, trong hoặc sau khi đánh giá các bầu cử sơ bộ khác. Nếu bất kỳ lệnh gọi nào trả về giá trị khác không là trạng thái thoát, thì tìm tiện ích sẽ trả về trạng thái thoát khác không. Một đối số chỉ chứa hai ký tự "{}" sẽ được thay thế bằng tập hợp các tên đường dẫn tổng hợp, với mỗi tên đường dẫn được truyền dưới dạng một đối số riêng cho tiện ích được gọi theo cùng thứ tự mà nó được tổng hợp. Kích thước của bất kỳ bộ hai hoặc nhiều tên đường dẫn sẽ bị giới hạn sao cho việc thực thi tiện ích không làm cho giới hạn {ARG_MAX} của hệ thống bị vượt quá . Nếu có nhiều hơn một đối số chứa hai ký tự "{}", hành vi không được chỉ định.

Khi độ dài của tên tệp bạn tìm thấy vượt quá hệ thống ARG_MAX, lệnh sẽ được thực thi.

Bạn có thể nhận được ARG_MAXbằng cách sử dụng getconf :

$ getconf ARG_MAX
2097152

Trên một số hệ thống, giá trị thực tế ARG_MAXcó thể khác nhau, bạn có thể tham khảo tại đây để biết thêm chi tiết.


Tôi đã chạy thử nghiệm bằng cách sử dụng find / -exec echo | wcvà đo tỷ lệ giữa số ký tự và số dòng tôi thấy rằng độ dài dòng lệnh tối đa được sử dụng findnhỏ hơn đáng kể so với giới hạn POSIX trên lý thuyết và gần hơn với Size of command buffer we are actually usingdòng trong đầu ra xargs --show-limits. Điều này đúng với Linux và nó có thể đúng với việc triển khai Mac OS find, mặc dù xargssẽ không in giá trị trong Mac OS. Bất cứ ý tưởng về lý do tại sao điều này xảy ra?
pqnet

--show-limitskhông được chỉ định bởi POSIX, việc triển khai Mac OS xargskhông hỗ trợ nó. find / -exec echo | wcsẽ không làm việc Hãy nhớ rằng ARG_MAXtrả về byte. Và đó là độ dài tối đa của các đối số cho các exec(3)hàm.
cuonglm

Tôi biết --show-limitskhông phải là POSIX, mặc dù đây không phải là độ dài đối số tối đa được sử dụng bởi find, sử dụng giá trị nhỏ hơn. Tôi không hiểu tại sao bạn nói rằng nó find / -exec echo | wcsẽ không hoạt động: theo tôi đó là một cách tốt để ước tính giá trị thực (và từ những gì tôi có thể thấy, tốt hơn là sử dụng getconf ARG_MAX). Ngoài ra, hệ thống tập tin của tôi chủ yếu là nếu không phải tất cả các ký tự ASCII, vì vậy số lượng ký tự gần bằng số byte.
pqnet

@pqnet: sử dụng find / -exec sh -c 'echo $@ | wc -c' _ {} +isntead.
cuonglm

xin lỗi tôi đã viết sai, tôi thực sự đã sử dụngfind / -exec echo {} + | wc -lc
pqnet

7

Có độ dài tối đa của danh sách đối số cho một quy trình mới trong hệ thống POSIX. findsẽ phân chia thực thi nếu đường dẫn tệp dài hơn này. Để xem giới hạn trên Linux, hãy sử dụng xargs --show-limits(không hoạt động trong Mac OS, nếu ai đó biết cách thay thế tốt hơn, vui lòng bình luận tại đây)

chỉnh sửa: bị đánh cắp trực tiếp từ câu trả lời của Gnouc, cách POSIX để có được độ dài tối đa của danh sách đối số là getconf ARG_MAX. Tuy nhiên, tôi đã chạy thử nghiệm trên máy mac os của mình và có vẻ như findsử dụng hơn một nửa số đó. Điều này phù hợp với thực tế là, trên hệ thống nơi nó hoạt động, xargs --show-limitscho chúng ta biết rằng nó sẽ không sử dụng độ dài đối số tối đa (trong trường hợp này cũng sẽ sử dụng khoảng một nửa số đó), tuy nhiên tôi không thể tìm thấy lời giải thích cho điều đó

chỉnh sửa 2: có vẻ như cách đáng tin cậy duy nhất để xác định có bao nhiêu tham số findsẽ dính vào nhau cho mỗi lần gọi là thử nghiệm, ví dụ như bằng cách chạy

find / -exec echo {} + | wc -cl

Vì đầu ra từ findcó một dòng cho mỗi lần echogọi, nên có thể đếm chúng bằng cách sử dụng wc -l. Tổng số byte echoed là đầu ra wc -cthay thế. Chia từng cái một, bạn sẽ có được số byte trung bình trong các tham số cho mỗi lần gọi lệnh (mặc dù giá trị thấp hơn một chút, vì làm tròn, khoảng một nửa chiều dài trung bình của một đường dẫn trong hệ thống của bạn)


xargskhông sử dụng toàn bộ thời lượng đối số tối đa vì nhiều chương trình trả trước một vài đối số bổ sung và sau đó chuyển các đối số cho các chương trình khác. Nếu xargsđiền các đối số đến mức tối đa tuyệt đối, các chương trình như vậy sẽ bị hỏng, bởi vì sẽ không có chỗ cho các đối số phụ đó.
hvd

@hvd có ý nghĩa. Nhưng sau đó, có một cách POSIX để biết bao nhiêu bộ đệm được sử dụng bởi xargshoặc find?
pqnet

Bạn có thể thực thi nó với một danh sách các đối số rất dài, xác định có bao nhiêu đối số được truyền trong lần gọi đầu tiên (giống như yes . | xargs | head -n 1 | wc -c) và so sánh nó với đầu ra của getconf ARG_MAX. Nhưng, thực sự đã thử nó trên hệ thống của tôi, tôi nhận được một sự khác biệt quá lớn đến nỗi dường như có nhiều điều này hơn tôi biết.
hvd

vì vậy nó sôi sục để thử nghiệm ... Tôi sẽ cập nhật câu trả lời của tôi
pqnet
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.