Có cách nào để buộc find
lệnh dừng lại ngay sau khi tìm thấy trận đấu đầu tiên không?
Có cách nào để buộc find
lệnh dừng lại ngay sau khi tìm thấy trận đấu đầu tiên không?
Câu trả lời:
Với GNU hoặc FreeBSD find
, bạn có thể sử dụng -quit
vị ngữ:
find . ... -print -quit
find
Tương đương NetBSD :
find . ... -print -exit
Nếu tất cả những gì bạn làm là in tên và giả sử tên tệp không chứa ký tự dòng mới, bạn có thể làm:
find . ... -print | head -n 1
Điều đó sẽ không dừng lại find
sau trận đấu đầu tiên, nhưng có thể, tùy thuộc vào thời gian và đệm vào trận đấu thứ hai hoặc (nhiều) sau đó. Về cơ bản, find
sẽ bị chấm dứt với SIGPIPE khi nó cố gắng xuất một cái gì đó trong khi head
đã biến mất vì nó đã đọc và hiển thị dòng đầu vào đầu tiên.
Lưu ý rằng không phải tất cả các shell sẽ chờ find
lệnh đó sau khi head
đã trả về. Shell Bourne và các triển khai AT & T của ksh
(khi không tương tác) và yash
(chỉ khi đường ống đó là lệnh cuối cùng trong tập lệnh) sẽ không làm cho nó chạy ở chế độ nền. Nếu bạn muốn thấy hành vi đó trong bất kỳ shell nào, bạn luôn có thể thay đổi ở trên thành:
(find . ... -print &) | head -n 1
Nếu bạn đang làm nhiều hơn là in đường dẫn của các tệp được tìm thấy, bạn có thể thử phương pháp này:
find . ... -exec sh -c 'printf "%s\n" "$1"; kill "$PPID"' sh {} \;
(thay thế printf
bằng bất cứ điều gì bạn sẽ làm với tập tin đó).
Điều đó có tác dụng phụ là find
trả lại trạng thái thoát phản ánh thực tế rằng nó đã bị giết.
Trên thực tế, sử dụng tín hiệu SIGPIPE thay vì SIGTERM ( kill -s PIPE
thay vì kill
) sẽ khiến một số shell im lặng hơn về cái chết đó (nhưng vẫn sẽ trả về trạng thái thoát khác không).
if [[ $(find ... -print -quit) ]]; then ...
Nó chỉ kiểm tra xem có tìm thấy gì không.
$(…)
phần trong dấu ngoặc kép trong trường hợp bạn chỉ sử dụng dấu ngoặc đơn ( [ … ]
).
[
là một lệnh tiêu chuẩn. Đó không phải là quá nhiều lệnh đó là khủng khiếp nhưng cách vỏ sò giống như Bourne phân tích các dòng lệnh. [[...]]
là một cấu trúc ksh có các vấn đề của riêng nó trong các shell khác nhau. Ví dụ, cho đến gần đây [[ $(...) ]]
sẽ không hoạt động zsh
(bạn cần [[ -n $(...) ]]
). Ngoại trừ zsh
, bạn cần trích dẫn [[ $a = $b ]]
, [[ =~ ]]
có sự khác biệt không tương thích giữa các lần triển khai và thậm chí giữa các phiên bản cho bash và một số lỗi trong một số. Cá nhân, tôi thích [
.
...
gì .
find . -name something -print -quit
Chấm dứt tìm thấy sau trận đấu đầu tiên sau khi in nó.
Chấm dứt tìm sau một số lượng phù hợp cụ thể và in kết quả:
find . -name something -print | head -n 5
Đáng ngạc nhiên là đủ - bây giờ đầu chấm dứt chuỗi sau 5 trận đấu, mặc dù tôi không biết làm thế nào hoặc tại sao.
Nó rất dễ dàng để kiểm tra. Chỉ cần tìm kiếm trên một root sẽ dẫn đến hàng ngàn, thậm chí có thể nhiều trận đấu hơn trong khi mất ít nhất một phút hoặc hơn. Nhưng khi được dẫn vào "head" "find" sẽ chấm dứt sau khi số lượng dòng được chỉ định trong đầu (đầu mặc định hiển thị 10, sử dụng "head -n" để chỉ định các dòng).
Lưu ý rằng điều này sẽ chấm dứt sau khi "head -n" đạt đến số lượng ký tự dòng mới được chỉ định và do đó, bất kỳ trận đấu nào chứa nhiều ký tự dòng mới sẽ được tính tương ứng.
Đối với mục đích giải trí, đây là một máy phát tìm lười biếng ở Bash. Ví dụ này tạo ra một vòng trên các tệp trong thư mục hiện tại. Đọc tuy nhiên nhiều bạn muốn sau đó kill %+
(có thể chỉ 1)
#!/usr/bin/env bash
unset -v files n
trap 'kill "$x_PID"' EXIT
coproc x while :; do
find . -type f -maxdepth 1 -exec sh -c "$(</dev/fd/3)" _ {} +
done 4<&0 <<\EOF 3<&0 <&4-
for x; do
read -r _
printf '%s\0' "$x"
done
EOF
while
echo >&${x[1]}
IFS= read -rd '' -u "$x" 'files[n++]'
do
printf '%q ' "${files[@]}"
echo
sleep .2
done
grep cũng trả về nếu được sử dụng với cờ -m
, vì vậy với
find stuff | grep -m1 .
nó sẽ trở lại sau dòng đầu tiên được in bằng find.
Sự khác biệt giữa điều này và find stuff -print -quit | head -1
là nếu tìm kiếm đủ nhanh, grep có thể không thể dừng quá trình kịp thời (mặc dù không thực sự quan trọng), trong khi nếu tìm kiếm lâu thì sẽ không cần tìm để in nhiều thứ không cần thiết dòng.
thay vào đó, nó hoạt động với findbox, mặc dù vì busybox grep cũng -m
không thực sự cần thiết
find /tmp/stuff -exec "sh" "-c" "eval 'echo {}; { kill \$PPID; }'" \;
điều này sẽ tạo ra một thông báo về quá trình tìm kiếm đã nhận được tín hiệu sigterm (thường), nhưng đầu ra này thuộc về shell đang chạy, không phải là lệnh find để nó không gây rối với đầu ra lệnh, nghĩa là các đường ống hoặc chuyển hướng sẽ chỉ xuất ra dòng phù hợp bởi tìm.