Đây là một hạn chế của find
. Các POSIX tiêu chuẩn quy định cụ thể rằng tình trạng trả lại find
là 0, trừ khi một lỗi xảy ra trong khi vượt qua các thư mục; trạng thái trả về của các lệnh được thực thi không nhập vào nó.
Bạn có thể tạo các lệnh ghi trạng thái của chúng vào một tệp hoặc tới một mô tả:
find_status_file=$(mktemp findstatus)
: >"$find_status_file"
find … -exec sh -c 'trap "echo \$?" EXIT; invalid_command "$0"' {} \;
if [ -s "$find_status_file" ]; then
echo 1>&2 "An error occurred"
fi
rm -f "$find_status_file"
Một phương pháp khác, như bạn đã khám phá , là sử dụng xargs. Các xargs
lệnh luôn xử lý tất cả các tệp, nhưng trả về trạng thái 1 nếu bất kỳ lệnh nào trả về trạng thái khác.
find … -print0 | xargs -0 -n1 invalid_command
Tuy nhiên, một phương pháp khác là tránh find
và sử dụng tính năng đệ quy trong vỏ thay thế: **/
có nghĩa là bất kỳ độ sâu của các thư mục con. Điều này đòi hỏi phiên bản 4 trở lên của bash; macOS bị kẹt ở phiên bản 3.x, vì vậy bạn phải cài đặt nó từ bộ sưu tập cổng. Sử dụng set -e
để tạm dừng tập lệnh trên lệnh đầu tiên trả về trạng thái khác không.
shopt -s globstar
set -e
for x in **/*.xml; do invalid_command "$x"; done
Xin lưu ý rằng trong bash 4.0 đến 4.2, điều này hoạt động nhưng đi qua các liên kết tượng trưng đến các thư mục, điều này thường không được mong muốn.
Nếu bạn sử dụng zsh thay vì bash, tính năng đệ quy đệ quy sẽ không có vấn đề gì. Zsh có sẵn theo mặc định trên OSX / macOS. Trong zsh, bạn chỉ có thể viết
set -e
for x in **/*.xml; do invalid_command "$x"; done
xargs
tiếp cận hoạt động nói chung nhưng bằng cách nào đó phá vỡbash -c
các lệnh. Ví dụ :find . -name '*.xml' -print0 | xargs -0 -n 1 -I '{}' bash -c "foo {}"
. Điều này được thực hiện nhiều lần trong khifind . -name '2*.xml' -print0 | xargs -0 -n 1 -I '{}' foo {}
được thực hiện một lần và thất bại. Bất cứ ý tưởng tại sao?