Nota:
* Esta respuesta probablemente va más allá de lo que garantiza el caso de uso, y find 2>/dev/nullpuede 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 findllamadas 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 bashozsh , hay una solución que es robusta a la vez que es razonablemente simple , utilizando solo findcaracterísticas compatibles con POSIX ; Si bien bashno 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 grepla 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 | catal 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>>(...)
bashzshksh2> >(...)ksh 93u+
grep -v 'Permission denied'filtra hacia fuera ( -v) (todas las líneas del findflujo stderr del comando) que contienen la frase Permission deniedy salidas de las líneas restantes a stderr ( >&2).
Este enfoque es:
robusto : grepsolo 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 : findel 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 findel 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>&1debe ser lo primero .
La captura de salida estándar en un archivo por adelantado permite 2>&1enviar solo mensajes de error a través de la tubería, que grepluego pueden funcionar sin ambigüedades.
El único inconveniente es que el código de salida general será el grepcomando , no el comando , lo findque 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, findel 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 findel 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 1ser así, de lo 0contrario.
En otras palabras: el código de salida ahora refleja la verdadera intención del comando: 0se 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 findel 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 3se usa para intercambiar temporalmente stdout ( 1) y stderr ( 2), de modo que los mensajes de error solo se puedan canalizar a greptravés de stdout.
Sin estas redirecciones, los datos (rutas de archivo) y los mensajes de error se canalizarían a greptravés de stdout, y grepluego 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 -prunerx-pruner
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 findcomando, 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
-namefiltro, de la siguiente manera:
find . ! -readable -prune -o -name '*.txt'
Esto, sin embargo, no funciona según lo previsto, porque -printse 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_folderscomo é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_filecorre 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.findse deba enfatizar y anunciar la preservación del código de salida: el código defindsalida es notoriamente inútil. Aquí, es muy probable que sea distinto de cero (e inútilmente).execute/searchpermiso de modo de archivo para 'buscar' un directorio (recuperar los inodos de los archivos contenidos).findhace esto para descender a un subdirectorio (además de requerirreadpermiso para listar los archivos en un directorio). Esto no es un 'error' o 'error de portabilidad'.Utilizar:
Esto oculta no solo los
Permission deniederrores, 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
findcomando es:2>&1 > files_and_folders |. La tubería redirige la salida estándar algrepcomando y se aplica primero. El2>&1envía el error estándar al mismo lugar que la salida estándar (la tubería). El> files_and_foldersenví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 defindse escribe en el archivo. Elgrepfiltra 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>&2significa 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
findque tiene en su sistema, puede haber opciones alternativas disponibles. GNUfinden 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:
-readableprueba coincide con archivos legibles. El!operador devuelve verdadero, cuando la prueba es falsa. Y! -readablecoincide con directorios no legibles (y archivos).-pruneacción no desciende al directorio.! -readable -prunese puede traducir a: si el directorio no es legible, no descienda a él.-readableprueba tiene en cuenta las listas de control de acceso y otros artefactos de permisos que la-permprueba ignora.Vea también
find(1) la página de manual para más detalles.fuente
-o:find . ! -readable -prune -o -name '*.txt'findno incluye-readablecomo una opción; tampoco lo hacefindpara BSD y, por lo tanto, para Mac OS X (no estoy seguro acerca de otros sistemas). Entonces, donde tiene GNUfindgarantizado, esto funciona muy bien, pero no es obvio cómo adaptarlo si no puede garantizar que el sistema tenga GNUfindinstalado. (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' -printSi 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,expectes simplemente el nombre del archivo que este comando intentará encontrar.Tubería
stderra/dev/nullmediante el uso de 2> / dev / nullfind . -name '...' 2>/dev/nullfuente
find . -name '...' -print 2>/dev/nullTambién puede usar los predicados
-permy-prunepara 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+rsimplemente coincide con los archivos que tienen elrpermiso (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 -printsería la buena solución.-readablecon-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=rlas impresionesfile, ya que su usuario leer es algo establecido, pero se relaciona con el delnobodyusuario, 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
-readablecambio, 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/nulltodaví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/nullen 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$?-execopción para tomar más medidas sobre los archivos o directorios encontrados porfindcomando.du -ch file_patterncalcula el tamaño de cada archivo que coincidefile_patterny 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 totalsolo 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.1siPermission deniedse imprimiera algún error ' 'Respuesta robusta para GNU
find:find . -type d \! \( -readable -executable \) -prune -print -o -print > files_and_foldersPase opciones adicionales a
findeso-prune(evite descender a) pero aún-printcualquier directorio ( ) que no tenga ( ) permisos y ambos , o ( ) cualquier otro archivo.-typed\!-readable-executable-o-print-readabley las-executableopciones 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>&1Use 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=Cestablece el entorno local POSIX utilizando una variable de entorno ,3>&2 2>&1 1>&3y3>&2 2>&1descriptores 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 porgrepaproximar el comportamiento original defind.'Permission denied'errores debidos a la redirección de salida (por ejemplo, si elfiles_and_foldersarchivo en sí no se puede escribir)fuente
-permno 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=rimpresionesfile, porque su bit de lectura del usuario está configurado, pero se relaciona con elnobodyusuario , no el usuario actual. El usuario actual no puede leer este archivo; tratarcat file.-permno 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 errorfindo 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
niceyfind $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