¿Puedo hacer que `find` return no sea 0 cuando no se encuentran archivos coincidentes?

46

Incluso cuando /tmpno se ha llamado ningún archivo something, al buscarlo findse devolverá 0:

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

¿Cómo puedo obtener un estado de salida distinto de cero cuando findno encuentro nada?

yael
fuente

Respuestas:

44

Aquí hay una frase que creo que hace lo que quieres:

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

El estado de retorno será 0cuando se encuentre algo y, de lo contrario, no será cero.

Si también necesita capturar la salida de findpara un procesamiento posterior, la respuesta de Sven lo ha cubierto.

Steven Monday
fuente
14
El seguimiento *de la egrepexpresión regular es completamente redundante. Puesto que no se está utilizando egrepla sintaxis de expresiones regulares, el viejo y simple greppuede haber algunos microsegundos más rápido.
tripleee
aprendí a usarfind ... | read
Sam
14

La solución más simple que no imprime, pero sale 0 cuando se encuentran resultados

find /tmp -name something | grep -q "."
Matt Kneiser
fuente
2
Las comillas dobles no sirven para nada aquí.
haridsv
Si bien las comillas dobles no tienen función de código, sí aclaran al lector que el carácter de punto es una expresión regular y no un directorio.
Dharma Bellamkonda
13

La salida 0 es fácil con find, la salida> 0 es más difícil porque eso generalmente solo ocurre con un error. Sin embargo, podemos hacer que suceda:

if find -type f -exec false {} +
then
  echo 'nothing found'
else
  echo 'something found'
fi
Steven Penny
fuente
2
Por lo que puedo decir, esto no funciona. El código de salida de findno parece depender de los códigos de salida de ninguno de los -execs que ejecutó.
Chris
@Chris funciona para mí y los 4 que votaron
Steven Penny,
ejemplo de resultado erróneamente falso de esta solución: find / existentes-punto-inicial / no-existente-punto-inicial -name archivo-en-existente-punto-inicial -exec falso {} +
Gerald Schade
2
Esto funciona correctamente y está documentado (aunque oculto en la execsección, no bajo el valor de retorno). No puede diferenciar entre nada encontrado y encontrarse con errores (por ejemplo, cuando se invocó en un punto de partida inexistente).
Tgr
Si necesita esta funcionalidad - sí
Gerald Schade
7

Después de encontrar esta pregunta mientras trataba de encontrar la manera de resolver un problema con Puppet (cambiar los permisos en las carpetas de un directorio pero no en el directorio en sí), esto parece funcionar:

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

Mi caso de uso específico es este:

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

Que saldrá del código 1 si el comando find no encuentra archivos con los permisos requeridos.

shearn89
fuente
Algunas soluciones (no las probé todas) aquí no funcionaron en una Mac; Esto lo hizo.
Alex Hall
5

No es posible. Find devuelve 0 si sale con éxito, incluso si no encontró un archivo (que es un resultado correcto que no indica un error cuando el archivo no existe).

Para citar la página de búsqueda

ESTADO DE SALIDA

buscar salidas con estado 0 si todos los archivos se procesan correctamente, mayor que 0 si se producen errores. Esta es deliberadamente una descripción muy amplia, pero si el valor de retorno no es cero, no debe confiar en la exactitud de los resultados de find.

Dependiendo de lo que desee lograr, podría intentar dejar encontrar -printel nombre de archivo y probarlo con su salida:

#!/bin/bash
MYVAR=`find . -name "something" -print`
if [ -z "$MYVAR" ]; then
    echo "Notfound"
else
   echo $MYVAR
fi
Sven
fuente
Ciertamente es posible , aunque no tan robusto como uno podría desear.
Ruslan
La página del manual está mal organizada; lo que dijo Ruslan está documentado bajo la opción exec/ execdir(usado con +):If any invocation returns a non-zero value as exit status, then find returns a non-zero exit status.
Tgr
1

Siento que este es el método más conciso y directo:

test `find /tmp/ -name something -print -quit 2>/dev/null`
Danorton
fuente
2
En este caso, si find tiene un error, imprimirá el resultado en / dev / null, devolverá una salida distinta de cero y luego el comando de prueba lo fijará a 0.
Jeff Ferland
No creo que sea verdad. Por favor describa su ejemplo. Si hay un error y encuentra salidas, la cadena estará vacía y la prueba devolverá un valor distinto de cero.
danorton
No estoy seguro de cuál podría ser su ejemplo, pero omití accidentalmente -print -quit, lo que podría abordar su preocupación.
danorton
¿Quizás la otra persona que votó en contra (presumiblemente por la misma razón) puede proporcionar un ejemplo contrario?
danorton
1
Está bien, simplemente no te gusta mi estilo. Para mis casos de uso, cualquier error que se encuentre puede ser ruidoso o tan grave que aparecerán en otro lugar. En cualquier caso, este método responde correctamente la última pregunta: "¿Hay un archivo accesible en la ruta por el nombre?" Un error devolverá una respuesta correcta de "No". Si quiero averiguar por qué no, puedo agregar un código más complejo que responda preguntas que originalmente no se plantearon aquí.
danorton
0

Aquí hay un pequeño guión que llamé test.py. Mejora con respecto a otros métodos publicados, ya que devolverá un código de error si se establece uno, y además establece uno si find no enumera ningún archivo:

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)

Aquí está la salida de la línea de comandos:

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

Luego, para un resultado donde find tenía errores pero encontró archivos:

$ 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

Luego, si desea la lista de archivos, puede hacer uso de -print 0pasar findy dividir la variable en nulos, o simplemente puede agregarle una declaración de impresión.

Jeff Ferland
fuente
-1

No es solo findque devuelve los códigos de estado de salida como cero cuando tiene éxito. En unix, cualquiera que sea el comando que ejecute, si tiene éxito, devuelve el estado de salida como cero.

Informatica-Oracle-Unix
fuente