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
?{ find . 3>&2 2>&1 1>&3 | grep -v 'Permission denied' >&3; } 3>&2 2>&1
>(...)
son específicas de Bash.find
se deba enfatizar y anunciar la preservación del código de salida: el código defind
salida es notoriamente inútil. Aquí, es muy probable que sea distinto de cero (e inútilmente).execute/search
permiso de modo de archivo para 'buscar' un directorio (recuperar los inodos de los archivos contenidos).find
hace esto para descender a un subdirectorio (además de requerirread
permiso para listar los archivos en un directorio). Esto no es un 'error' o 'error de portabilidad'.Utilizar:
Esto oculta no solo los
Permission denied
errores, por supuesto, sino todos los mensajes de error.Si realmente desea mantener otros posibles errores, como demasiados saltos en un enlace simbólico, pero no los permisos denegados, probablemente tenga que adivinar que no tiene muchos archivos llamados 'permiso denegado' y prueba:
Si estrictamente desea filtrar solo el error estándar, puede usar la construcción más elaborada:
La E / S de redirección en el
find
comando es:2>&1 > files_and_folders |
. La tubería redirige la salida estándar algrep
comando y se aplica primero. El2>&1
envía el error estándar al mismo lugar que la salida estándar (la tubería). El> files_and_folders
envía salida estándar (pero no error estándar) a un archivo. El resultado neto es que los mensajes escritos en el error estándar se envían por la tubería y la salida regular defind
se escribe en el archivo. Elgrep
filtra la salida estándar (que puede decidir lo selectivo que quiere que sea, y puede tener que cambiar la ortografía según la zona y O / S) y la final>&2
significa que los mensajes de error supervivientes (escritos en la salida estándar) van al error estándar una vez más. La redirección final podría considerarse como opcional en el terminal, pero sería una muy buena idea usarla en un script para que los mensajes de error aparezcan en el error estándar.Hay infinitas variaciones sobre este tema, dependiendo de lo que quieras hacer. Esto funcionará en cualquier variante de Unix con cualquier derivado de shell Bourne (Bash, Korn, ...) y cualquier versión compatible con POSIX de
find
.Si desea adaptarse a la versión específica
find
que tiene en su sistema, puede haber opciones alternativas disponibles. GNUfind
en particular tiene una miríada de opciones que no están disponibles en otras versiones; vea la respuesta actualmente aceptada para uno de esos conjuntos de opciones.fuente
2>/dev/null
, ¡sin espacio!2>
es una sola unidad sin espacios; puede tener un espacio entre este y el nombre del archivo. De manera similar con otras redirecciones, como2>&1
(que redirige el error estándar al mismo lugar donde se produce la salida estándar), o2>&-
que cierra el error estándar, etc. Consulte Redirecciones para obtener los detalles sangrientos restantes. (El código anterior es un shell genérico similar a POSIX, no específico debash
).Utilizar:
o más generalmente
Funciona con: find (GNU findutils) 4.4.2. Antecedentes:
-readable
prueba coincide con archivos legibles. El!
operador devuelve verdadero, cuando la prueba es falsa. Y! -readable
coincide con directorios no legibles (y archivos).-prune
acción no desciende al directorio.! -readable -prune
se puede traducir a: si el directorio no es legible, no descienda a él.-readable
prueba tiene en cuenta las listas de control de acceso y otros artefactos de permisos que la-perm
prueba ignora.Vea también
find
(1) la página de manual para más detalles.fuente
-o
:find . ! -readable -prune -o -name '*.txt'
find
no incluye-readable
como una opción; tampoco lo hacefind
para BSD y, por lo tanto, para Mac OS X (no estoy seguro acerca de otros sistemas). Entonces, donde tiene GNUfind
garantizado, esto funciona muy bien, pero no es obvio cómo adaptarlo si no puede garantizar que el sistema tenga GNUfind
instalado. (Funcionará bien en Linux; puede o no funcionar en otro lugar).find . ! -readable -prune -o -name '*.txt'
no parece funcionar en Ubuntu 14.04 usando find 4.2.2. Parece ingore-name
. Por alguna extraña razón con la que tengo éxitofind . \( ! -readable -prune \) -o -name '*.txt' -print
Si desea comenzar la búsqueda desde la raíz "/", probablemente verá resultados como:
Es por permiso. Para resolver esto:
Puedes usar el comando sudo:
Pide la contraseña del superusuario, cuando ingrese la contraseña verá el resultado que realmente desea. Si no tiene permiso para usar el comando sudo, lo que significa que no tiene una contraseña de superusuario, primero solicite al administrador del sistema que lo agregue al archivo sudoers.
¡Puede usar redirigir la Salida de error estándar desde (Generalmente Pantalla / Pantalla) a algún archivo y evitar ver los mensajes de error en la pantalla! redirigir a un archivo especial / dev / null:
Puede utilizar redirigir la salida de error estándar de (Pantalla / pantalla general) a la salida estándar (pantalla / pantalla general), luego canalizar con el comando grep con el parámetro -v "invertir" para no ver las líneas de salida que tienen 'Permiso denegado' pares de palabras:
fuente
sudo find...
Tuve que usar:
especificando el nombre de lo que quería encontrar y luego diciéndole que redirija todos los errores a / dev / null
esperar ser la ubicación del programa de esperar que estaba buscando.
fuente
expect
. En cambio,expect
es simplemente el nombre del archivo que este comando intentará encontrar.Tubería
stderr
a/dev/null
mediante el uso de 2> / dev / nullfind . -name '...' 2>/dev/null
fuente
find . -name '...' -print 2>/dev/null
También puede usar los predicados
-perm
y-prune
para evitar descender a directorios ilegibles (consulte también ¿Cómo elimino las declaraciones de impresión de "permiso denegado" del programa find? - Unix & Linux Stack Exchange ):fuente
-perm -g+r,u+r,o+r
simplemente coincide con los archivos que tienen elr
permiso (lectura) establecido para los 3 principios de seguridad del archivo , lo que no tiene relación directa con si el usuario actual puede leer ese archivo o no. Tiene el potencial de perder archivos que el usuario actual puede leer y hacer coincidir los archivos que no puede leer.find . -type d ! \( -perm -u+r -o -perm -g+r -o -perm -o+r \) -prune -o -print
sería la buena solución.-readable
con-perm
- ver mi comentario anterior y considerar este ejemplo:echo 'hi' > file; sudo chown nobody:nobody file; sudo chmod o-r file; find file -perm -u=r
las impresionesfile
, ya que su usuario leer es algo establecido, pero se relaciona con el delnobody
usuario, no el usuario actual. El usuario actual no puede leer este archivo; tratarcat file
. Ver también: esta respuesta mía.Error estándar de redireccionamiento. Por ejemplo, si está utilizando bash en una máquina Unix, puede redirigir el error estándar a / dev / null de esta manera:
fuente
Si bien los enfoques anteriores no abordan el caso de Mac OS X porque Mac Os X no admite el
-readable
cambio, así es como puede evitar errores de 'Permiso denegado' en su salida. Esto podría ayudar a alguien.find / -type f -name "your_pattern" 2>/dev/null
.Si está utilizando algún otro comando con
find
, por ejemplo, para encontrar el tamaño de los archivos de cierto patrón en un directorio2>/dev/null
todavía funcionaría como se muestra a continuación.find . -type f -name "your_pattern" -exec du -ch {} + 2>/dev/null | grep total$
.Esto devolverá el tamaño total de los archivos de un patrón dado. Tenga
2>/dev/null
en cuenta el al final del comando find.fuente
2>/dev/null
. ¿Puedes por favor explicar la parte-exec du -ch {} + 2>/dev/null | grep total$
?-exec
opción para tomar más medidas sobre los archivos o directorios encontrados porfind
comando.du -ch file_pattern
calcula el tamaño de cada archivo que coincidefile_pattern
y la última línea de esa salida es el gran total de todos los archivos que coinciden con elfile_pattern
. Vea la página del manual paradu
.grep total
solo filtra la línea que extrae el total general (que es la última línea).Esos errores se imprimen en la salida de error estándar (fd 2). Para filtrarlos, simplemente redirija todos los errores a / dev / null:
o primero une stderr y stdout y luego elimina esos errores específicos:
fuente
Respuesta simple:
find . > files_and_folders 2>&-
2>&-
cierra (-
) el descriptor de archivo de error estándar (2
) para que todos los mensajes de error sean silenciados.1
siPermission denied
se imprimiera algún error ' 'Respuesta robusta para GNU
find
:find . -type d \! \( -readable -executable \) -prune -print -o -print > files_and_folders
Pase opciones adicionales a
find
eso-prune
(evite descender a) pero aún-print
cualquier directorio ( ) que no tenga ( ) permisos y ambos , o ( ) cualquier otro archivo.-type
d
\!
-readable
-executable
-o
-print
-readable
y las-executable
opciones son extensiones GNU, no forman parte del estándar POSIXPermission denied
' en archivos anormales / corruptos (p. Ej., Vea el informe de error que afecta a los sistemas de archivos montados en contenedores usandolxcfs
<v2.0.5)Respuesta robusta que funciona con cualquier compatible con POSIX
find
(GNU, OSX / BSD, etc.){ LC_ALL=C find . 3>&2 2>&1 1>&3 > files_and_folders | grep -v 'Permission denied'; [ $? = 1 ]; } 3>&2 2>&1
Use una tubería para pasar el flujo de error estándar a
grep
, eliminando todas las líneas que contienen la'Permission denied'
cadena.LC_ALL=C
establece el entorno local POSIX utilizando una variable de entorno ,3>&2 2>&1 1>&3
y3>&2 2>&1
descriptores de archivos duplicados a la tubería de la corriente de error estándar agrep
, y[ $? = 1 ]
usos[]
para invertir el código de error devuelto porgrep
aproximar el comportamiento original defind
.'Permission denied'
errores debidos a la redirección de salida (por ejemplo, si elfiles_and_folders
archivo en sí no se puede escribir)fuente
-perm
no vale la pena presentar la solución basada, porque más fundamentalmente de lo que sugiere la cita hace algo diferente de lo previsto: es una prueba puramente centrada en el archivo , relacionada con el propietario del archivo y grupo, ninguno de los cuales tiene ninguna relación garantizada con el usuario que llama al comando (vea esta respuesta mía. Parece que su solución GNU revisada ahora no captura los permisos de permiso denegado que se derivan de los archivos .echo 'hi' > file; sudo chown nobody:nobody file; sudo chmod o-r file; find file -perm -u=r
impresionesfile
, porque su bit de lectura del usuario está configurado, pero se relaciona con elnobody
usuario , no el usuario actual. El usuario actual no puede leer este archivo; tratarcat file
.-perm
no funciona para determinar los permisos actuales del usuario. Se eliminó esa alternativa de esta respuesta.Para evitar solo las advertencias de permiso denegado, diga a find que ignore los archivos ilegibles eliminándolos de la búsqueda. Agregue una expresión como OR a su búsqueda, como
Esto generalmente dice (emparejar un archivo ilegible y podarlo de la lista) O (emparejar un nombre como * .jbd y mostrarlo [con ls]) . (Recuerde que, de manera predeterminada, las expresiones son AND juntas, a menos que use -o.) Necesita -ls en la segunda expresión o find puede agregar una acción predeterminada para mostrar cualquiera de las coincidencias, que también le mostrará todos los archivos ilegibles .
Pero si está buscando archivos reales en su sistema, generalmente no hay razón para buscar en / dev, que tiene muchos archivos, por lo que debe agregar una expresión que excluya ese directorio, como:
Entonces (coincide con el archivo ilegible y poda de la lista) O (coincide con la ruta / dev y poda de la lista) O (coincide con el archivo como * .jbd y lo muestra) .
fuente
utilizar
Es estúpido (porque eleva la búsqueda) y no es seguro, pero es mucho más corto de escribir.
fuente
sudo
. Corre el riesgo de que todo el sistema se vea afectado por un errorfind
o una versión maliciosa, o una invocación incorrecta que escriba algo inesperadamente, lo que no podría suceder si ejecutara esto con los privilegios normales.Ninguna de las respuestas anteriores funcionó para mí. Lo que encuentre en Internet se centra en: ocultar errores. Ninguno maneja correctamente el proceso código de retorno / código de salida. Uso el comando find dentro de los scripts de bash para localizar algunos directorios y luego inspeccionar su contenido. Evalúo el comando find success usando el código de salida: un valor cero funciona, de lo contrario falla.
La respuesta proporcionada por Michael Brux funciona a veces. ¡Pero tengo un escenario en el que falla! Descubrí el problema y lo arreglé yo mismo. Necesito podar archivos cuando:
Ver el tema clave aquí es: AND / OR. Una buena secuencia de condición sugerida que leí es:
Esto no funciona siempre. Esto significa que se activa una ciruela pasa cuando una coincidencia es:
Esta secuencia de expresiones falla cuando se concede acceso de lectura pero no lo es el acceso de ejecución.
Después de algunas pruebas, me di cuenta de eso y cambié mi solución de script de shell a:
La clave aquí es colocar el "no verdadero" para una expresión combinada:
De lo contrario, no tiene acceso completo, lo que significa: podarlo. Esto me funcionó en un escenario en el que las soluciones sugeridas anteriormente fallaron.
Proporciono a continuación los detalles técnicos para preguntas en la sección de comentarios. Pido disculpas si los detalles son excesivos.
fuente
nice
yfind $HOME -maxdepth 5 -follow ...
?${m_find_name}
), y contiene varias opciones que no son pertinentes a la cuestión (nice
,/home*
,-maxdepth 5
,-follow
). Agregué una respuesta que aborda el problema específico de 'filtrar directorios legibles pero no ejecutables' de manera más concisa, sin dejar de ser de uso general.Puede usar el grep -v invert-match
Me gusta esto:
Debería a la magia
fuente
- = Para MacOS = -
Haga un nuevo comando usando un alias: simplemente agregue ~ / .bash_profile line:
y en la nueva ventana de Terminal puedes llamarlo:
fuente
Si está utilizando CSH o TCSH, aquí hay una solución:
Si desea salida a la terminal:
Sin embargo, como se describe en las preguntas frecuentes "csh-whynot", no debe usar CSH.
fuente