Nota:
* Esta respuesta probablemente va más allá de lo que garantiza el caso de uso, y find 2>/dev/null
puede ser lo suficientemente buena en muchas situaciones. Todavía puede ser de interés para una perspectiva multiplataforma y para su discusión de algunas técnicas avanzadas de shell en el interés de encontrar una solución lo más sólida posible, a pesar de que los casos protegidos pueden ser en gran medida hipotéticos.
* Si su sistema está configurado para mostrar mensajes de error localizados , prefije las find
llamadas a continuación con LC_ALL=C
( LC_ALL=C find ...
) para asegurarse de que se informan los mensajes en inglés , de modo que grep -v 'Permission denied'
funcione según lo previsto. Invariablemente, sin embargo, cualquier mensaje de error que no va a ser visualizado entonces serán en Inglés también.
Si su shell es bash
ozsh
, hay una solución que es robusta a la vez que es razonablemente simple , utilizando solo find
características compatibles con POSIX ; Si bien bash
no es parte de POSIX, la mayoría de las plataformas modernas de Unix vienen con él, lo que hace que esta solución sea ampliamente portátil:
find . > files_and_folders 2> >(grep -v 'Permission denied' >&2)
Nota: Existe una pequeña posibilidad de que parte de grep
la salida de la unidad llegue después de find
completarse, porque el comando general no espera >(...)
a que termine el comando interno . En bash
, puede evitar esto agregando | cat
al comando.
>(...)
es una sustitución del proceso de salida (rara vez utilizada) que permite redirigir la salida (en este caso, stderr output ( ) al stdin del comando interno .
Además de y , en principio , también los admite , pero tratando de combinarlos con la redirección desde stderr , como se hace aquí ( ), parece ser ignorado silenciosamente (in ).2>
>(...)
bash
zsh
ksh
2> >(...)
ksh 93u+
grep -v 'Permission denied'
filtra hacia fuera ( -v
) (todas las líneas del find
flujo stderr del comando) que contienen la frase Permission denied
y salidas de las líneas restantes a stderr ( >&2
).
Este enfoque es:
robusto : grep
solo se aplica a los mensajes de error (y no a una combinación de rutas de archivos y mensajes de error, lo que puede dar lugar a falsos positivos), y los mensajes de error que no sean permisos denegados se pasan a stderr.
sin efectos secundarios : find
el código de salida se conserva: la imposibilidad de acceder al menos a uno de los elementos del sistema de archivos encontrados da como resultado un código de salida 1
(aunque eso no le dirá si se produjeron errores además de los permisos denegados (también)).
Soluciones compatibles con POSIX:
Las soluciones totalmente compatibles con POSIX tienen limitaciones o requieren trabajo adicional.
Si find
el resultado se captura en un archivo de todos modos (o se suprime por completo), entonces la solución basada en la tubería de la respuesta de Jonathan Leffler es simple, robusta y compatible con POSIX:
find . 2>&1 >files_and_folders | grep -v 'Permission denied' >&2
Tenga en cuenta que el orden de las redirecciones es importante: 2>&1
debe ser lo primero .
La captura de salida estándar en un archivo por adelantado permite 2>&1
enviar solo mensajes de error a través de la tubería, que grep
luego pueden funcionar sin ambigüedades.
El único inconveniente es que el código de salida general será el grep
comando , no el comando , lo find
que en este caso significa: si no hay errores en absoluto o solo errores de permiso denegado, el código de salida será 1
( falla de señalización ), de lo contrario ( errores distintos a los de permiso denegado) 0
, que es lo contrario de la intención.
Dicho esto, find
el código de salida rara vez se usa de todos modos , ya que a menudo transmite poca información más allá de la falla fundamental , como pasar una ruta inexistente.
Sin embargo, el caso específico de incluso solo algunosde las rutas de entrada que son inaccesibles debido a la falta de permisos se refleja en find
el código de salida (tanto en GNU como en BSD find
): si se produce un error de permisos denegados para cualquiera de los archivos procesados, el código de salida se establece en 1
.
La siguiente variación aborda eso:
find . 2>&1 >files_and_folders | { grep -v 'Permission denied' >&2; [ $? -eq 1 ]; }
Ahora, el código de salida indica si se produjo algún error que no sea el caso Permission denied
: de 1
ser así, de lo 0
contrario.
En otras palabras: el código de salida ahora refleja la verdadera intención del comando: 0
se informa de éxito ( ), si no se produjo ningún error o solo se produjeron errores de permiso denegado.
Esto podría decirse que es incluso mejor que simplemente pasar find
el código de salida, como en la solución en la parte superior.
gniourf_gniourf en los comentarios propone una generalización (aún compatible con POSIX) de esta solución utilizando redireccionamientos sofisticados , que funciona incluso con el comportamiento predeterminado de imprimir las rutas de archivo a stdout :
{ find . 3>&2 2>&1 1>&3 | grep -v 'Permission denied' >&3; } 3>&2 2>&1
En resumen: el descriptor de archivo personalizado 3
se usa para intercambiar temporalmente stdout ( 1
) y stderr ( 2
), de modo que los mensajes de error solo se puedan canalizar a grep
través de stdout.
Sin estas redirecciones, los datos (rutas de archivo) y los mensajes de error se canalizarían a grep
través de stdout, y grep
luego no podrían distinguir entre el mensaje de error Permission denied
y un archivo (hipotético) cuyo nombre contiene la frase Permission denied
.
Sin embargo, como en la primera solución, el código de salida informado será grep
's, no find
' s, pero se puede aplicar la misma solución que la anterior.
Notas sobre las respuestas existentes:
Hay varios puntos a tener en cuenta sobre la respuesta de Michael Brux , find . ! -readable -prune -o -print
:
Requiere GNU find
; en particular, no funcionará en macOS. Por supuesto, si solo necesita el comando para trabajar con GNU find
, esto no será un problema para usted.
TodavíaPermission denied
pueden aparecer algunos errores : informa dichos errores para los elementos secundarios de los directorios para los cuales el usuario actual tiene permiso, pero carece de permiso (ejecutable). La razón es que debido a que el directorio en sí es legible, no se ejecuta, y el intento de descender a ese directorio desencadena los mensajes de error. Dicho esto, el caso típico es que falte el permiso.find ! -readable -prune
r
x
-prune
r
Nota: El siguiente punto es una cuestión de filosofía y / o caso de uso específico, y puede decidir que no es relevante para usted y que el comando se adapta bien a sus necesidades, especialmente si simplemente imprime las rutas:
- Si conceptualiza el filtrado de los mensajes de error de permiso denegado, una tarea separada que desea poder aplicar a cualquier
find
comando, entonces el enfoque opuesto de prevenir proactivamente los errores de permiso denegado requiere la introducción de "ruido" en el find
comando, que también introduce complejidad y dificultades lógicas .
- Por ejemplo, el comentario más votado sobre la respuesta de Michael (al momento de escribir este artículo) intenta mostrar cómo extender el comando al incluir un
-name
filtro, de la siguiente manera:
find . ! -readable -prune -o -name '*.txt'
Esto, sin embargo, no funciona según lo previsto, porque -print
se requiere la acción final. (se puede encontrar una explicación en esta respuesta ). Tales sutilezas pueden introducir errores.
La primera solución en la respuesta de Jonathan Leffler , find . 2>/dev/null > files_and_folders
como él mismo afirma, ciegamente silencia todos los mensajes de error (y la solución es engorroso y no totalmente robusta, ya que también explica). Hablando pragmáticamente , sin embargo, es la solución más simple , ya que puede contentarse con suponer que todos los errores estarían relacionados con los permisos.
La respuesta de la niebla , sudo find . > files_and_folders
, es conciso y pragmático, pero poco aconsejable para otra cosa que no sea simplemente la impresión de nombres de archivo , por razones de seguridad: debido a que se está ejecutando como la raíz del usuario ", se arriesga a que todo el sistema está en mal estado por un error en hallazgo o una versión maliciosa, o una invocación incorrecta que escribe algo inesperadamente, lo que no podría suceder si ejecutaras esto con privilegios normales "(de un comentario sobre la respuesta de mist por tripleee ).
La segunda solución en la respuesta de viraptor , find . 2>&1 | grep -v 'Permission denied' > some_file
corre el riesgo de falsos positivos (debido al envío de una mezcla de stdout y stderr a través de la tubería), y, potencialmente, en lugar de informar no errores -permission-negado a través de stderr, capturas de ellos junto a las rutas de salida en el archivo de salida.
find . 2>&1 > files_and_folders | grep -v 'Permission denied' >&2
?