Чи є спосіб змусити find
команду зупинитися відразу після пошуку першого матчу?
Чи є спосіб змусити find
команду зупинитися відразу після пошуку першого матчу?
Відповіді:
За допомогою GNU або FreeBSD find
ви можете використовувати -quit
предикат:
find . ... -print -quit
find
Еквівалент NetBSD :
find . ... -print -exit
Якщо все, що ви робите, це друк цього імені та припускаючи, що в назви файлів не містяться символи нового рядка, ви можете зробити:
find . ... -print | head -n 1
Це не зупиниться find
після першого матчу, але можливо, залежно від часу та буферизації другого матчу чи (набагато) пізніше. В основному, find
він закінчується SIGPIPE, коли він намагається вивести щось, поки head
він уже не пішов, оскільки він вже прочитав і відобразив перший рядок введення.
Зауважте, що не всі оболонки будуть чекати цієї find
команди після head
повернення. Оболонки Bourne та реалізація AT&T ksh
(коли не інтерактивна) та yash
(тільки якщо цей конвеєр є останньою командою у скрипті) не будуть, залишаючи його працювати у фоновому режимі. Якщо ви краще бачите таку поведінку в будь-якій оболонці, ви завжди можете змінити вищезазначене на:
(find . ... -print &) | head -n 1
Якщо ви робите більше, ніж друкуєте шляхи знайдених файлів, ви можете спробувати такий підхід:
find . ... -exec sh -c 'printf "%s\n" "$1"; kill "$PPID"' sh {} \;
(замініть printf
тим, що ви робили з цим файлом).
Це має побічний ефект find
повернення статусу виїзду, що відображає той факт, що він був убитий.
Насправді, використання сигналу SIGPIPE замість SIGTERM ( kill -s PIPE
замість kill
) призведе до того, що деякі снаряди мовчать про цю смерть (але все одно повернуть ненульовий статус виходу).
if [[ $(find ... -print -quit) ]]; then ...
він просто перевіряє, чи знайти друковане щось взагалі.
$(…)
частину в лапки, якщо ви використовуєте лише одні дужки ( [ … ]
).
[
це стандартна команда. Розбирається не стільки команда, яка жахлива, скільки те, як аналогічні оболонки Борна аналізують командні рядки. [[...]]
це ksh конструкція, яка має власні проблеми в різних оболонках. Наприклад, до недавнього часу [[ $(...) ]]
він не працював zsh
(вам потрібно [[ -n $(...) ]]
). Крім у zsh
вас, вам потрібні цитати [[ $a = $b ]]
, у [[ =~ ]]
несумісних відмінностях між реалізаціями та навіть між версіями для bash та декількома помилками в деяких. Особисто я віддаю перевагу [
.
...
? .
find . -name something -print -quit
Скасовується після першої відповідності після друку.
Скасувати пошук після певної кількості збігів та друку результатів:
find . -name something -print | head -n 5
Дивно, але зараз голова припиняє струну після 5 матчів, хоча я не знаю як і чому.
Це дуже просто перевірити. Дозвольте знайти пошук у корені, що призведе до тисяч, а може й більше збігів, займаючи хоча б хвилину чи більше. Але при передачі в "head" "пошук" закінчується після вказаної кількості рядків, визначених у заголовку (за замовчуванням головка показує 10, використовуйте "head -n", щоб вказати рядки).
Зауважте, що це припиняється після досягнення "head -n" заданого числа символів нового рядка, і тому будь-яка відповідність, що містить кілька символів нового рядка, буде підрахована відповідно.
Для розважальних цілей ось лінивий генератор пошуку в Bash. Цей приклад генерує дзвінок над файлами в поточному каталозі. Прочитайте скільки завгодно тоді бажаєте kill %+
(можливо, лише 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 також повертається, якщо використовується з прапором -m
, так, з
find stuff | grep -m1 .
вона повернеться після першого рядка, надрукованого знахідкою.
Різниця між цим find stuff -print -quit | head -1
полягає в тому, що якщо пошук буде досить швидким, греп може не встигнути зупинити процес вчасно (хоча це не дуже важливо), тоді як якщо пошук тривалий, він буде зайвим знайти, щоб надрукувати багато непотрібного лінії.
це натомість працює з зайняттям пошуку в скриньці, хоча, оскільки у грепса для заняття також є, -m
він насправді не потрібен
find /tmp/stuff -exec "sh" "-c" "eval 'echo {}; { kill \$PPID; }'" \;
це випустить повідомлення про процес пошуку, отримавши (зазвичай) сигнал підписи, але цей вихід належить запущеній оболонці, а не команді find, тому він не возиться з командним висновком, тобто труби або переспрямовування будуть виводити тільки рядок відповідні знахідці.