Busque archivos ejecutables usando el comando buscar

113

¿Qué tipo de parámetro / bandera puedo usar con el findcomando Unix para buscar ejecutables?

Bueno en realidad
fuente
escriba 'hombre encontrar'. Creo que '-executable' es la opción que desea.
sje397
3
find -executable... pero esto no garantiza que todos los archivos enumerados se ejecuten realmente
William
1
No todas las implementaciones de findson iguales. Es posible que la opción recomendada por @ sje397 y @William no esté disponible. Es mejor utilizar la solución aceptada que se muestra a continuación.
LS
No me gustan todas las propuestas que se muestran a continuación, que se basan en permisos de archivo. Argumentación: para mi sistema operativo GNU (Ubuntu) es posible establecer una bandera "x" (ejecutable) para, por ejemplo, un archivo de texto ASCII. Ningún mímico impidió que esta operación se completara con éxito. Solo necesita un pequeño error / error para que varios archivos no intencionados se asignen la bandera x. Por lo tanto, las soluciones gniourf_gniourf 'son mis favoritas. Sin embargo, tiene el inconveniente de que, para los ejecutables de compilación cruzada, se necesita un emulador o dispositivo de destino.
Na13-c

Respuestas:

173

En las versiones GNU de find puedes usar -executable:

find . -type f -executable -print

Para las versiones BSD de find, puede usar -permcon +y una máscara octal:

find . -type f -perm +111 -print

En este contexto, "+" significa "cualquiera de estos bits está establecido" y 111 son los bits de ejecución.

Tenga en cuenta que esto no es idéntico al -executablepredicado en GNU find. En particular, -executableprueba que el usuario actual puede ejecutar el archivo, mientras que -perm +111solo prueba si se ha establecido algún permiso de ejecución.

Las versiones anteriores de GNU find también admiten la -perm +111sintaxis, pero a partir de 4.5.12 esta sintaxis ya no es compatible. En su lugar, puede utilizar -perm /111para obtener este comportamiento.

Laurence Gonsalves
fuente
Error find: invalid mode ‘+111’en findutils 4.5.11 4.fc20.
sourcejedi
1
@sourcejedi Gracias. En realidad, solo estaba hablando de versiones no GNU de find (BSD, en particular), pero las versiones anteriores de GNU find también admitían esa sintaxis. En las versiones más recientes, tendrá que usar en /lugar de +. Consulte la respuesta actualizada para obtener más detalles.
Laurence Gonsalves
De hecho, leí mal tu respuesta. Perdón por hacerlo más complicado :).
sourcejedi
Si los enlaces simbólicos deben también ser encontrados en los archivos ejecutables, incluya la -Lopción: find -L ....
mklement0
Me tomó un tiempo comprender las implicaciones de "no es idéntico al predicado-ejecutable" y "solo prueba si se establece algún permiso de ejecución": Significa que -perm +111puede producir falsos positivos , es decir, archivos que el usuario actual no puede ejecutar. No hay forma de emular -executablesolo probando los permisos, porque lo que se necesita es relacionar la identidad de usuario y grupo del archivo con el usuario actual .
mklement0
35

Sugerencia del sombrero para @ gniourf_gniourf por aclarar un error fundamental.

Esta respuesta intenta proporcionar una descripción general de las respuestas existentes y discutir sus sutilezas y méritos relativos , así como proporcionar información de fondo , especialmente con respecto a la portabilidad .

Encontrar archivos ejecutables puede hacer referencia a dos casos de uso distintos :

  • centrado en el usuario : encuentra archivos que son ejecutables por el usuario actual .
  • centrado en archivos: busque archivos que tengan (uno o más) bits de permisos ejecutables establecidos .

Tenga en cuenta que en cualquier escenario puede tener sentido usarlo enfind -L ... lugar de solo find ...para encontrar también enlaces simbólicos a ejecutables .

Tenga en cuenta que el caso más simple centrado en archivos, buscar ejecutables con el bit de permisos ejecutables establecido para TODOS los tres principales de seguridad (usuario, grupo, otro), normalmente , pero no necesariamente, producirá los mismos resultados que el escenario centrado en el usuario, y es importante entender la diferencia.

Centrado en el usuario ( -executable)

  • La respuesta aceptada recomienda encomiablemente -executable, SI GNU find está disponible.

    • GNU findviene con la mayoría de las distribuciones de Linux
      • Por el contrario, las plataformas basadas en BSD, incluido macOS, vienen con BSD find, que es menos potente.
    • Según lo requiera el escenario, -executablesolo coincide con los archivos que el usuario actual puede ejecutar (hay casos extremos. [1] ).
  • La alternativa BSD find ofrecida por la respuesta aceptada ( -perm +111) responde a una pregunta diferente , centrada en el archivo (como dice la propia respuesta).

    • Usar solo -permpara responder la pregunta centrada en el usuario es imposible , porque lo que se necesita es relacionar la identidad del usuario y del grupo del archivo con el usuario actual , mientras -permque solo se pueden probar los permisos del archivo .
      Usando solo las findfunciones POSIX , la pregunta no se puede responder sin involucrar utilidades externas.
    • Por lo tanto, lo mejor que se -permpuede hacer (por sí mismo) es una aproximación de -executable. Quizás una aproximación más cercana de lo que -perm +111es-perm -111 , para encontrar archivos que tengan el bit ejecutable configurado para TODOS los principales de seguridad (usuario, grupo, otros); esto me parece el escenario típico del mundo real. Como beneficio adicional, también es compatible con POSIX (utilícelo find -Lpara incluir enlaces simbólicos, consulte más abajo para obtener una explicación):

      find . -type f -perm -111  # or: find . -type f -perm -a=x
  • La respuesta de gniourf_gniourf proporciona un verdadero equivalente portátil de-executable usar-exec test -x {} \;, aunque a expensas del rendimiento .

    • La combinación -exec test -x {} \; con -perm +111(es decir, archivos con al menos un conjunto de bits ejecutables) puede ayudar al rendimiento ya que execno es necesario invocarlo para cada archivo (lo siguiente usa el equivalente compatible con POSIX de BSD find -perm +111/ GNU find -perm /111; consulte más adelante para obtener una explicación) :

      find . -type f \( -perm -u=x -o -perm -g=x -o -perm -o=x \) -exec test -x {} \; -print

Centrado en archivos ( -perm)

  • Para responder preguntas centradas en archivos , es suficiente usar el -permprimario compatible con POSIX (conocido como prueba en la terminología de búsqueda de GNU).
    • -permle permite probar los permisos de cualquier archivo, no solo la ejecución.
    • Los permisos se especifican en modo octal o simbólico . Los modos octales son números octales (p. Ej., 111), Mientras que los modos simbólicos son cadenas (p a=x. Ej., ).
    • Los modos simbólicos identifican los principales de seguridad como u(usuario), g(grupo) y o(otro), o apara referirse a los tres. Los permisos se expresan como xejecutables, por ejemplo, y se asignan a los principales que utilizan operadores =, +y -; para una discusión completa, incluidos los modos octales, consulte la especificación POSIX de la chmodutilidad .
    • En el contexto de find:
      • Prefijar un modo con- (por ejemplo, -ug=x) significa: archivos coincidentes que tienen todos los permisos especificados (pero los archivos coincidentes pueden tener permisos adicionales).
      • No tener prefijo (por ejemplo 755) significa: hacer coincidir archivos que tienen este conjunto completo y exacto de permisos.
      • Advertencia : tanto la búsqueda de GNU como la búsqueda de BSD implementan un prefijo adicional no estándar con lógica son-CUALQUIERA-de-los-bits-de-permiso-especificados , pero hágalo con una sintaxis incompatible :
        • BSD encontrar: +
        • Búsqueda GNU: / [2]
      • Por lo tanto, evite estas extensiones, si su código debe ser portátil .
  • Los ejemplos siguientes demuestran respuestas portátiles a varias preguntas centradas en archivos.

Ejemplos de comandos centrados en archivos

Nota:

  • Los siguientes ejemplos son compatibles con POSIX , lo que significa que deberían funcionar en cualquier implementación compatible con POSIX, incluyendo GNU find y BSD find; específicamente, esto requiere:
    • NO usar prefijos de modo no estándar +o /.
    • Usando las formas POSIX de los operadores lógicos primarios :
      • !para NOT (GNU find y BSD find también permiten -not); tenga en cuenta que \!se utiliza en los ejemplos para proteger !de las expansiones del historial de shell
      • -apara AND (GNU find y BSD find también permiten -and)
      • -opara OR (GNU find y BSD find también permiten -or)
  • Los ejemplos utilizan modos simbólicos , porque son más fáciles de leer y recordar.
    • Con el prefijo de modo -, los operadores =y +se pueden usar indistintamente (por ejemplo, -u=xes equivalente a -u+x, a menos que lo aplique -xmás adelante, pero no tiene sentido hacerlo).
    • Úselo ,para unir modos parciales; Y la lógica está implícita; por ejemplo, -u=x,g=xsignifica que se deben establecer tanto el bit ejecutable del usuario como del grupo.
    • Los modos no pueden expresar por sí mismos una coincidencia negativa en el sentido de "coincidencia sólo si este bit NO está establecido"; debe utilizar una separada -permde expresión con el NO primaria, !.
  • Tenga en cuenta que los primarios de find (como -print, o -perm; también conocidos como acciones y pruebas en GNU find) se unen implícitamente con -a(AND lógico), y que -oy posiblemente los paréntesis (escapados como \(y \)para el shell) son necesarios para implementar la lógica OR.
  • find -L ...en lugar de solo find ...se usa para hacer coincidir enlaces simbólicos con ejecutables
    • -Lindica a find que evalúe los destinos de los enlaces simbólicos en lugar de los propios enlaces simbólicos; por lo tanto, sin -L, -type fignoraría los enlaces simbólicos por completo.
# Match files that have ALL executable bits set - for ALL 3 security
# principals (u (user), g (group), o (others)) and are therefore executable
# by *anyone*.
# This is the typical case, and applies to executables in _system_ locations
# (e.g., /bin) and user-installed executables in _shared_ locations
# (e.g., /usr/local/bin), for instance. 
find -L . -type f -perm -a=x  # -a=x is the same as -ugo=x

# The POSIX-compliant equivalent of `-perm +111` from the accepted answer:
# Match files that have ANY executable bit set.
# Note the need to group the permission tests using parentheses.
find -L . -type f \( -perm -u=x -o -perm -g=x -o -perm -o=x \)

# A somewhat contrived example to demonstrate the use of a multi-principial
# mode (comma-separated clauses) and negation:
# Match files that have _both_ the user and group executable bit set, while
# also _not_ having the other executable bit set.
find -L . -type f -perm -u=x,g=x  \! -perm -o=x

[1] Descripción de -executabledesde man findGNU encontrar 4.4.2:

Coincide con archivos que son ejecutables y directorios que se pueden buscar (en un sentido de resolución de nombre de archivo). Esto tiene en cuenta las listas de control de acceso y otros artefactos de permisos que la prueba -perm ignora. Esta prueba hace uso de la llamada al sistema de acceso (2), por lo que puede ser engañado por servidores NFS que hacen mapeo de UID (o aplastamiento de raíz), ya que muchos sistemas implementan acceso (2) en el kernel del cliente y por lo tanto no pueden hacer uso de la información de mapeo de UID almacenada en el servidor. Debido a que esta prueba se basa únicamente en el resultado de la llamada al sistema de acceso (2), no hay garantía de que un archivo para el que esta prueba tenga éxito pueda realmente ejecutarse.

[2] GNU encuentra versiones anteriores a la 4.5.12 que también permitían el prefijo +, pero primero se desaprobó y finalmente se eliminó, porque la combinación +con modos simbólicos produce probablemente resultados inesperados debido a que se interpreta como una máscara de permisos exacta . Si usted (a) se ejecutan en una versión anterior 4.5.12 y (b) se limite a octales modos solamente, usted podría salir con el uso +de ambas GNU encontrar y BSD hallazgo, pero no es una idea buena.

mklement0
fuente
2
¿La respuesta SO más completa de la historia? ;)
andynormancx
@andynormancx :) Bueno, en términos de cantidad de viñetas, puedo ofrecer este contendiente .
mklement0
11

Para tener otra posibilidad 1 de encontrar los archivos que son ejecutables por el usuario actual:

find . -type f -exec test -x {} \; -print

(el comando de prueba aquí es el que se encuentra en PATH, muy probablemente /usr/bin/test, no el incorporado).


1 ¡ Úselo solo si la -executablebandera de findno está disponible! esto es sutilmente diferente de la -perm +111solución.

gniourf_gniourf
fuente
2
Esto funciona, pero es bastante lento. Además, dependiendo del shell, es posible que deba ajustar o escapar del marcador de posición del nombre de archivo, como '{}'o \{\}.
Ionoclast Brigham
1
@ mklement0 esto no encontrará los comandos que son ejecutables por mí como lo -executablehace o como lo hace mi comando.
gniourf_gniourf
1
Gracias, @gniourf_gniourf. Realmente tuve algunos conceptos erróneos allí. Estoy reimprimiendo su otro comentario aquí, porque al menos por ahora estoy eliminando mi respuesta (tal vez para resucitar, SI hay algo que se pueda salvar): " nofind . -type f -perm -u=x es el equivalente de : coincide con todos los archivos que el usuario puede ejecutar, y estos incluyen si estoy en el grupo adecuado o . De hecho , encontraré muchos archivos que el usuario no puede ejecutar y perderé algunos que el usuario pueda ejecutar ". -executable-executableg+xo+x-perm -u=x
mklement0
1
@IonoclastBrigham: Si bien tener que citar {}es una necesidad hipotética (y citar no duele), en la práctica no es necesario en shells tipo POSIX y csh. ¿Sabe usted conchas donde se se requiere?
mklement0
4
@IonoclastBrigham: Interesante, gracias; por lo que, en fish, de {}hecho debe escaparse como '{}'o \{\}. Tenga en cuenta que bash, kshy zshproporcionan el mismo tipo de expansión de la riostra; sin embargo, imprimen el token sin comillas {} tal cual (y por lo tanto: no hay necesidad de escapar), porque NO lo consideran una expresión de llave válida (requieren al menos 2 tokens, o una expresión de secuencia numérica válida), mientras que fish considera {}una llave válida expresión que da como resultado la cadena vacía .
mklement0
9

Puede utilizar la -executablebandera de prueba:

-executable
              Matches files which are executable  and  directories  which  are
              searchable  (in  a file name resolution sense).
codaddict
fuente
4
-executable es supuestamente una opción desconocida.
bueno, en realidad
4
¿Sería una extensión de GNU Find? Dado que la etiqueta es Unix, no Linux, al menos una extensión GNU debe documentarse como tal.
Jonathan Leffler
3
Esta opción no es compatible con el comando BSD find que se encuentra al menos en OS X. Esta es una extensión GNU, pero podría ser compatible con otras versiones de find.
Ionoclast Brigham
FWIW, encontré que esto no está en sles 10, sino en sles> = 11 (se quemó un poco)
Peter Turner
Tenga en cuenta que esto en realidad no incluye todos los ejemplos. En mi caso, tenía un archivo que poseía y -rw-r-xr-xque -executableno detecta
Dezza
2

Esto funcionó para mí y pensé en compartir ...

find ./ -type f -name "*" -not -name "*.o" -exec sh -c '
    case "$(head -n 1 "$1")" in
      ?ELF*) exit 0;;
      MZ*) exit 0;;
      #!*/ocamlrun*)exit0;;
    esac
exit 1
' sh {} \; -print
AjayKumarBasuthkar
fuente
13
¡Solo unos miles de casos más, y te habrás reinventado file!
tripleee
@tripleee +1. Genial sería esta extensión:find ./ -mime application/x-sharedlib -o -mime application/x-dosexec
Daniel Alder
@Daniel Alder, ¿qué versión de hallazgo usas? No encontré la opción -mime en find (GNU findutils) 4.4.2
AjayKumarBasuthkar
@tripleee +1. utilizar 'file' & / 'mimetype' es una buena idea o descubrir encontrar una versión que admita -mime es mejor. También me pregunto si 'file' / 'mimetype' tiene la opción de filtrar y mostrar solo ejecutables.
AjayKumarBasuthkar
2
find . -executable -type f

realmente no garantiza que el archivo sea ejecutable, encontrará archivos con el bit de ejecución establecido. Si lo haces

chmod a+x image.jpg

el hallazgo anterior pensará que image.jpg es un ejecutable incluso si en realidad es una imagen jpeg con el bit de ejecución establecido.

Generalmente soluciono el problema con esto:

find . -type f -executable -exec file {} \; | grep -wE "executable|shared object|ELF|script|a\.out|ASCII text"

Si desea que el hallazgo imprima información del domo sobre archivos ejecutables, puede hacer algo como esto:

find . -type f -executable -printf "%i.%D %s %m %U %G %C@ %p" 2>/dev/null |while read LINE
do
  NAME=$(awk '{print $NF}' <<< $LINE)
  file -b $NAME |grep -qEw "executable|shared object|ELF|script|a\.out|ASCII text" && echo $LINE
done

En el ejemplo anterior, el nombre de ruta completo del archivo está en el último campo y debe reflejar dónde lo buscas con awk "NAME = $ (awk '{print $ NF}' <<< $ LINE)" si el nombre del archivo estaba en otra parte de la cadena de salida de búsqueda necesita reemplazar "NF" con la posición numérica correcta. Si su separador no es un espacio, también necesita decirle a awk cuál es su separador.

louigi600
fuente
1

Es TAN ridículo que esto no sea súper fácil ... y mucho menos casi imposible . Manos arriba, me refiero a Apple / Spotlight ...

mdfind 'kMDItemContentType=public.unix-executable'

¡Al menos funciona!

Alex Grey
fuente
Es bueno saberlo mdfinden OSX. Tenga en cuenta que nuestro comando reporta ejecutables Unix para todo el sistema . mdfind -onlyin . 'kMDItemContentType=public.unix-executable'limita los resultados al subárbol del directorio actual. Puntos de interés menores: aparentemente no se admite limitar la búsqueda a un directorio específico (sin subcarpetas). Los enlaces simbólicos a archivos ejecutables aparentemente nunca se incluyen. Curiosamente, una vez que se mdfindha encontrado un archivo ejecutable, la eliminación posterior del bit ejecutable no se recoge.
mklement0
Creo que encontré errores en la forma en que Spotlight detecta / anula la detección de archivos ejecutables de Unix; Presenté un error con Apple y también en openradar.me/20162683 . Os animo - y cualquier persona interesada en esta funcionalidad - también abre una incidencia en error al bugreport.apple.com
mklement0
(Perdón por la ráfaga de comentarios; con suerte, ahora son correctos) se mdfind -onlyin . 'kMDItemContentType=public.unix-executable'comporta como lo find . -type f -perm +111 -printhace. Es decir, encuentra archivos con cualquier conjunto de bits ejecutables, lo que puede producir falsos positivos (aunque eso puede no ser un problema en la práctica); para encontrar realmente solo archivos ejecutables por el usuario actual usando BSD find, consulte la respuesta de @ gniourf_gniourf. El uso de una findsolución basada en una solución tiene la ventaja de que también puede encontrar enlaces simbólicos a archivos ejecutables, si lo desea (opción -L), lo que mdfindaparentemente no es posible.
mklement0
1
@ mklement0 mi respuesta evitó los adornos , para tratar de aclarar el punto, pero sí, casi nunca usarías esta forma "sin adornos". otra opción, no estoy seguro de si surgió, es el buen globbing ... ls /Applications/**/*(*)en tu (¿mi?) zshcaparazón
Alex Gray
Gracias por el útil zshconsejo, no lo sabía; (Parece que puede hacer coincidir ejecutables ( *) o enlaces simbólicos ( @), pero no ambos, ¿verdad?). En cuanto a su punto original: Permítame reiterar: find . -type f -perm +a=xhará lo que hace su mdfindcomando, al tiempo que proporciona más flexibilidad. Incluso puede reformularlo para que sea compatible con POSIX.
mklement0
1

Bueno, la respuesta fácil sería: "sus archivos ejecutables están en los directorios contenidos en su variable PATH", pero eso realmente no encontraría sus ejecutables y podría perder muchos ejecutables de todos modos.

No sé mucho sobre mac, pero creo que "mdfind 'kMDItemContentType = public.unix-ejecutable'" podría perder cosas como scripts interpretados

Si está bien que encuentre archivos con los bits ejecutables establecidos (independientemente de si son realmente ejecutables), entonces está bien hacerlo

find . -type f -perm +111 -print

donde sea compatible, la opción "-executable" hará un filtro adicional para buscar acl y otros artefactos de permisos, pero técnicamente no es muy diferente a "-pemr +111".

Tal vez en el futuro find admita "-magic" y le permita buscar explícitamente archivos con una identificación mágica específica ... pero luego tendría que especificar para multar todos los formatos ejecutables identificación mágica.

No conozco una salida fácil técnicamente correcta en Unix.

louigi600
fuente
1

Entonces, si realmente desea encontrar tipos de archivos ejecutables (por ejemplo, scripts, binarios ELF, etc.), no simplemente archivos con permiso de ejecución, entonces probablemente desee hacer algo más como esto (donde el directorio actual. Se puede reemplazar con lo que sea directorio que desee):

 gfind . -type f -exec bash -c '[[ $(file -b "'{}'") == *" executable "* ]] ' \; -print

O para aquellos de ustedes que no están usando macports (usuarios de linux) o que tienen instalado gnu find como find que desean:

 find . -type f -exec bash -c '[[ $(file -b "'{}'") == *" executable "* ]] ' \; -print

Aunque si está en OS X, viene con una pequeña utilidad escondida en algún lugar llamada is_exec que básicamente agrupa esa pequeña prueba para que pueda acortar la línea de comandos si la encuentra. Pero de esta manera es más flexible, ya que puede reemplazar fácilmente la prueba == con la prueba = ~ y usarla para buscar propiedades más complejas como archivos ejecutables de texto sin formato o cualquier otra información que devuelva el comando de archivo.


Las reglas exactas para las citas aquí son bastante opacas, así que termino resolviéndolas por prueba y error, pero me encantaría escuchar la explicación correcta.

Peter Gerdes
fuente
0

Tuve el mismo problema y la respuesta estaba en el código fuente de dmenu : la utilidad stest creada para ese propósito. Puede compilar los archivos 'stest.c' y 'arg.h' y debería funcionar. Hay una página de manual para el uso, que puse allí por conveniencia:

STEST(1)         General Commands Manual         STEST(1)

NAME
       stest - filter a list of files by properties

SYNOPSIS
       stest  [-abcdefghlpqrsuwx]  [-n  file]  [-o  file]
       [file...]

DESCRIPTION
       stest takes a list of files  and  filters  by  the
       files'  properties,  analogous  to test(1).  Files
       which pass all tests are printed to stdout. If  no
       files are given, stest reads files from stdin.

OPTIONS
       -a     Test hidden files.

       -b     Test that files are block specials.

       -c     Test that files are character specials.

       -d     Test that files are directories.

       -e     Test that files exist.

       -f     Test that files are regular files.

       -g     Test  that  files  have  their set-group-ID
              flag set.

       -h     Test that files are symbolic links.

       -l     Test the contents of a directory  given  as
              an argument.

       -n file
              Test that files are newer than file.

       -o file
              Test that files are older than file.

       -p     Test that files are named pipes.

       -q     No  files are printed, only the exit status
              is returned.

       -r     Test that files are readable.

       -s     Test that files are not empty.

       -u     Test that files have their set-user-ID flag
              set.

       -v     Invert  the  sense  of  tests, only failing
              files pass.

       -w     Test that files are writable.

       -x     Test that files are executable.

EXIT STATUS
       0      At least one file passed all tests.

       1      No files passed all tests.

       2      An error occurred.

SEE ALSO
       dmenu(1), test(1)

                        dmenu-4.6                STEST(1)
Josuah Demangeon
fuente