Как определить, «нашли» ли найденные совпадения?

16

Существуют ли идиоматические средства для обнаружения, найдены ли "найти" какие-либо совпадения? Я сейчас пользуюсь

COUNT=`find ... | wc -l`
if [ "$COUNT" -gt 0 ]; then

но это кажется немного косвенным для меня. Кроме того, я хотел бы найти, чтобы остановить поиск, как только он найдет совпадение, чтобы не тратить время и силы. Мне просто нужно знать, есть ли какие-либо файлы, которые соответствуют.

Обновление: я сделал ошибку, написав свой вопрос без кода передо мной: я использую wc -lдругой случай, когда мне все равно нужно знать общее количество найденных файлов. В случае, когда я только проверяю, есть ли совпадения, я использовал if [ -z $(find …) ].

Крис Пейдж
источник

Ответы:

17

Если вы знаете, что у вас есть GNU find, используйте, -quit чтобы он остановился после первого совпадения.

Портативно, труба выводит findв head -n 1. Этот путь findумрет от сломанного канала после нескольких совпадений (когда он заполнен headвходным буфером).

В любом случае вам не нужно wcпроверять, является ли строка пустой, оболочка может сделать это самостоятельно.

if [ -n "$(find … | head -n 1)" ]; then …
Жиль "ТАК - перестань быть злым"
источник
Интересно ... Я думал, что -nприменяется только к «определенным» переменным ($ abc, $ xyz и т. Д.), Но я предполагаю, что $ (...) - это «определенная» временная переменная .. +1 ... (и я просто недавно прочитал, что использование -nрискованно, если только вы не уверены, что переменная еще не объявлена ​​и не используется) ... но у temp такой возможности не будет ... т.е. неинициализированный против пустого
Peter.O
2
@fred: Напротив, -nпроверяет, является ли строка пустой, она не имеет ничего общего с переменными. То, что вы читали, вероятно, говорило, что использование -nне проверяет, определена ли переменная: -n "$foo"ложно, если fooопределено, но пусто, и отображает сообщение об ошибке в set -u. [ -n "${foo+1}" ]надежно проверяет, fooустановлен ли он, но обычно одинаково обрабатывает пустые и неустановленные переменные: [ -n "${foo:+1}" ]или просто, [ -n "$foo" ]если вас это не беспокоит set -u.
Жиль "ТАК - перестань быть злым"
Благодарность! У меня нет в -quitналичии, но трубопровод head -n 1работает (как и делает head -c 1, который останавливается еще раньше, но, вероятно, с незначительной выгодой). Также я сделал ошибку, написав свой вопрос без кода передо мной: я использую wc -lдругой случай, когда мне нужно знать общее количество найденных файлов. В случае, когда я только проверяю, есть ли совпадения, я использовал if [ -z `find … ` ].
Крис Пейдж
6

Вы можете использовать -quit действие, чтобы остановить после первого матча. Возможно, вы захотите объединить это с другим действием (например -print), или вы не сможете определить, нашел ли он что-нибудь.

Например, find ... -print -quitнапечатает путь к первому подходящему файлу и затем выйдет. Или вы можете использовать-printf 1 -quit для печати 1, если есть совпадение и ничего, если нет.

findСтатус выхода отражает наличие ошибок при поиске, а не обнаружил ли он что-либо, поэтому вы должны проверить его выходные данные, чтобы убедиться, что они совпадают.

CJM
источник
-quitявляется расширением GNU. Он не будет работать в системах, использующих другие реализации find (1), такие как OS X, BSD и, возможно, большинство коммерческих Unices.
Уоррен Янг
Спасибо, это полезно знать, если я использую другую систему. К сожалению, ни -quit, ни -printf недоступны на моем компьютере (Mac OS X).
Крис Пейдж
4

Выход 0 легко найти, выход> 0 сложнее, потому что обычно это происходит только с ошибкой. Однако мы можем сделать это:

if find -type f -exec false {} +
then
  echo 'nothing found'
else
  echo 'something found'
fi

Обратите внимание, что это решение более производительно, чем использование подоболочки; execing false, безусловно, быстрее, чем exe даже Dash:

$ cat alfa.sh bravo.sh charlie.sh delta.sh
find -name non-existing-file -exec false {} +
find -name existing-file -exec false {} +
[ "$(find -name non-existing-file)" ]
[ "$(find -name existing-file)" ]

$ strace dash alfa.sh | wc -l
807

$ strace dash bravo.sh | wc -l
1141

$ strace dash charlie.sh | wc -l
1184

$ strace dash delta.sh | wc -l
1194
Стивен Пенни
источник
0

Вы можете обернуть его в состояние оболочки, например:

[ "$(find . ...)" '!=' '' ] && echo Found || echo Not found

Где ...ваше условие соответствия, например-name *.txt .

Некоторые другие примеры:

[ "$(find /etc -name hosts)" ] && echo True || echo False
[ ! -z "$(find /etc -name hosts)" ] && echo True || echo False
kenorb
источник