Могу ли я заставить `find` возвращать не 0, если не найдено подходящих файлов?


46

Даже если /tmpфайл не вызван something, его поиск с помощью findвернет 0:

  $ find /tmp -name something 
  $ echo $?
  0

Как я могу получить ненулевой статус выхода, когда findничего не находит?

Ответы:


44

Вот строчка, которая, как я считаю, делает то, что вы хотите:

find /tmp -name something | egrep '.*'

Статус возврата будет, 0когда что-то найдено, и ненулевой в противном случае.

Если вам также нужно захватить вывод findдля дальнейшей обработки, то ответ Свена покрыл это.


14
Трейлинг *на egrepрегулярное выражение полностью излишним. Поскольку вы не используете egrepсинтаксис регулярных выражений, обычный старый grepможет быть на несколько микросекунд быстрее.
tripleee

я научился использоватьfind ... | read
Сэм

14

Самое простое решение, которое не печатает, но выходит 0, когда найдены результаты

find /tmp -name something | grep -q "."

2
Двойные кавычки здесь не имеют смысла.
haridsv

Хотя двойные кавычки не выполняют никакой функции кода, они все же позволяют читателю понять, что символ точки является регулярным выражением, а не каталогом.
Дхарма Белламконда

13

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

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

2
Насколько я могу судить, это не работает. Код выхода, по- findвидимому, не зависит от кодов выхода, которые -execон запускал.
Крис

@ Крис работает для меня, и 4, кто проголосовал
Стивен Пенни

пример неверно ложного результата этого решения: найти / существующая начальная точка / несуществующая начальная точка -имя файл-в-существующая начальная точка -exec false {} +
Джеральд Шаде

2
Это работает правильно и задокументировано (хотя и скрыто в execразделе, а не под возвращаемым значением). Он не может различить ничего не найденного и не обнаруживает ошибки (например, когда он был вызван на несуществующей начальной точке).
Tgr

Если вам нужна эта функциональность - да
Джеральд Шаде

7

После того, как я нашел этот вопрос, пытаясь найти способ решить проблему с Puppet (изменить разрешения для папок в каталоге, но не для самого каталога), похоже, это работает:

! test -z $(find /tmp -name something)

Мой конкретный вариант использования такой:

! test -z $(find /home -mindepth 1 -maxdepth 1 -perm -711)

Который выйдет из кода 1, если команда find не найдет файлы с необходимыми разрешениями.


Несколько решений (не пробовали их все) здесь не работали на Mac; это сделал.
Алекс Холл

5

Это невозможно. Функция Find возвращает 0, если она успешно завершается, даже если она не нашла файл (что является правильным результатом, не указывающим на ошибку, когда файл действительно не существует).

Цитировать страницу поиска

СТАТУС ВЫХОДА

найти выходы со статусом 0, если все файлы успешно обработаны, больше 0 при возникновении ошибок. Это намеренно очень широкое описание, но если возвращаемое значение не равно нулю, вам не следует полагаться на правильность результатов поиска.

В зависимости от того, чего вы хотите достичь, вы можете попытаться найти -printимя файла и проверить его вывод:

#!/bin/bash
MYVAR=`find . -name "something" -print`
if [ -z "$MYVAR" ]; then
    echo "Notfound"
else
   echo $MYVAR
fi

Это, конечно, возможно , хотя и не так надежно, как хотелось бы.
Руслан

Страница справочника плохо организована; то, что сказал Руслан, задокументировано в параметре exec/ execdir(используется с +):If any invocation returns a non-zero value as exit status, then find returns a non-zero exit status.
Tgr

1

Я чувствую, что это самый лаконичный и прямой метод:

test `find /tmp/ -name something -print -quit 2>/dev/null`

2
В этом случае, если find обнаружит ошибку, он выведет результат в / dev / null, вернет ненулевой выход, а затем исправит значение 0 с помощью команды test.
Джефф Ферланд

Я не верю, что это правда. Пожалуйста, опишите ваш пример. Если возникнет ошибка и найдены выходы, строка будет пустой, а test вернет ненулевое значение.
Данортон

Я не уверен, каким может быть ваш пример, но я случайно пропустил -print -quit, что могло бы решить вашу проблему.
Данортон

Возможно, другой человек, который проголосовал против (предположительно по той же причине), может привести противоположный пример?
Данортон

1
Ладно, тебе просто не нравится мой стиль. Для моих случаев использования любые обнаруженные ошибки могут быть либо шумовыми, либо настолько серьезными, что они будут появляться в других местах. В любом случае, этот метод правильно отвечает на главный вопрос: «Есть ли доступный файл по пути с заданным именем». Ошибка вернет правильный ответ «Нет». Если я хочу выяснить, почему нет, я могу добавить более сложный код, который отвечает на вопросы, изначально не задаваемые здесь.
Данортон

0

Вот маленький сценарий, который я назвал test.py. Он улучшает другие методы, опубликованные в том, что он вернет код ошибки, если он установлен, и дополнительно установит один, если find не перечислил никаких файлов:

from subprocess import Popen
import sys

p = Popen(['find'] + sys.argv)
out, err = p.communicate()
if p.returncode:
    sys.exit(p.returncode)
if not out:
    sys.exit(1)

Вот вывод командной строки:

$ python test.py . -maxdepth 1 -name notthere
$ echo $?
1
$ find . -maxdepth 1 -name notthere
$ echo $?
0
$ find . -failedarg
find: unknown predicate `-failedarg'
$ echo $?
1

Затем, для результата, где поиск имел ошибки, но нашел файлы:

$ ls -lh
$ d---------  2 jeff users   6 Feb  6 11:49 noentry
$ find .
.
./noentry
find: `./noentry': Permission denied
$ echo $?
1
$ find . | egrep '.*'
.
./noentry
find: `./noentry': Permission denied
$ echo $?
0
python ../test.py 
../test.py
$ echo $?
1

Затем, если вам нужен список файлов, вы можете использовать -print 0переданную findи разделить переменную out на нули, или вы можете просто добавить для нее оператор печати.


-1

Это не только findто, что возвращает коды состояния выхода как ноль, когда это успешно. В Unix какую бы команду вы ни выполняли, если она выполнена успешно, она возвращает статус выхода как ноль.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.