Unix find: recherche des fichiers exécutables

Quel type de paramètre / indicateur puis-je utiliser avec la commande de find Unix afin de rechercher des fichiers exécutables?

Sur les versions GNU de find, vous pouvez utiliser -executable :

 find . -type f -executable -print 

Pour les versions BSD de find, vous pouvez utiliser -perm avec + et un masque octal:

 find . -type f -perm +111 -print 

Dans ce contexte, “+” signifie “l’un quelconque de ces bits est défini” et 111 est les bits d’exécution.

Notez que ce n’est pas identique au prédicat -executable dans GNU find. En particulier, -executable teste que le fichier peut être exécuté par l’utilisateur actuel, tandis que -perm +111 teste simplement si des permissions d’exécution sont définies.

Les anciennes versions de GNU find prennent également en charge la syntaxe -perm +111 , mais à partir de la version 4.5.12, cette syntaxe n’est plus prise en charge. Au lieu de cela, vous pouvez utiliser -perm /111 pour obtenir ce comportement.

Astuce du chapeau à @ gniourf_gniourf pour éclaircir une idée fausse fondamentale.

Cette réponse tente de donner un aperçu des réponses existantes et de discuter de leurs subtilités et de leurs mérites respectifs , ainsi que de fournir des informations de base , notamment en ce qui concerne la portabilité .

La recherche de fichiers exécutables peut faire référence à deux cas d’utilisation distincts :

  • centré sur l’utilisateur : recherche les fichiers exécutables par l’utilisateur actuel .
  • centré sur les fichiers: recherche les fichiers qui ont (un ou plusieurs) bits d’autorisation exécutables définis .

Notez que dans l’un ou l’autre scénario, il peut être judicieux d’ utiliser find -L ... au lieu de simplement find ... afin de trouver également des liens symboliques vers les exécutables .

Notez que le cas le plus simple, centré sur les fichiers – recherche des fichiers exécutables avec les droits d’exécution exécutables définis pour TOUS les trois entités de sécurité (utilisateur, groupe, autre) – génère généralement , mais pas nécessairement, les mêmes résultats que le scénario centré sur l’utilisateur. important de comprendre la différence.

-executable sur l’utilisateur ( -executable )

  • La réponse acceptée recommande de manière louable -executable , SI GNU find est disponible.

    • GNU find est livré avec la plupart des dissortingbutions Linux
      • En revanche, les plates-formes basées sur BSD, y compris macOS, sont fournies avec BSD find, qui est moins puissant.
    • Au fur et à mesure que le scénario l’exige, -executable ne correspond qu’aux fichiers que l’ utilisateur actuel peut exécuter (il existe des cas d’arêtes. [1] ).
  • L’ alternative de find BSD proposée par la réponse acceptée ( -perm +111 ) répond à une question différente , centrée sur le fichier (comme l’indique la réponse elle-même).

    • L’utilisation de just -perm pour répondre à la question centrée sur l’ utilisateur est impossible , car il faut relier l’identité de l’utilisateur et du groupe du fichier à celle de l’ utilisateur actuel , tandis que -perm ne peut que tester les permissions du fichier .
      En utilisant uniquement les fonctionnalités de find POSIX , il est impossible de répondre à la question sans impliquer des utilitaires externes.
    • Ainsi, le meilleur que l’ -perm puisse faire (par lui-même) est une approximation de -executable . Peut-être une approximation plus proche de -perm +111 est -perm -111 , afin de trouver les fichiers dont le bit exécutable est défini pour TOUS les principaux responsables de la sécurité (utilisateur, groupe, autre) – cela me semble être le cas réel. En prime, il se trouve également être compatible POSIX (utilisez find -L pour inclure des liens symboliques, voir plus loin pour une explication):

       find . -type f -perm -111 # or: find . -type f -perm -a=x 
  • La réponse de gniourf_gniourf fournit un véritable équivalent portable de -executable , utilisant -exec test -x {} \; , mais au désortingment de la performance .

    • Combinaison -exec test -x {} \; avec -perm +111 (c.-à-d. des fichiers avec au moins un bit exécutable défini) peut aider les performances dans cet exec ne doivent pas être appelées pour chaque fichier (ce qui suit utilise l’équivalent de BSD find -perm +111 / GNU find -perm +111 -perm /111 ; voir plus loin pour une explication):

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

-perm sur les fichiers ( -perm )

  • Pour répondre aux questions centrées sur les fichiers , il suffit d’utiliser le -perm primaire compatible avec -perm (appelé test dans la terminologie GNU find).
    • -perm vous permet de tester toutes les permissions de fichiers, pas seulement l’exécutable.
    • Les permissions sont spécifiées en mode octal ou symbolique . Les modes octaux sont des nombres octaux (par exemple, 111 ), tandis que les modes symboliques sont des chaînes (par exemple, a=x ).
    • Les modes symboliques identifient les entités de sécurité comme u (utilisateur), g (groupe) et o (autre), ou a pour désigner les trois. Les permissions sont exprimées en x pour exécutable, par exemple, et affectées aux principaux à l’aide des opérateurs = , + et - ; Pour une discussion complète, y compris sur les modes octaux, consultez la spécification POSIX pour l’utilitaire chmod .
    • Dans le contexte de find :
      • Préfixer un mode avec - (par exemple, -ug=x ) signifie: faire correspondre les fichiers qui ont toutes les permissions spécifiées (mais les fichiers correspondants peuvent avoir des permissions supplémentaires).
      • Avoir un préfixe NO (par exemple 755 ) signifie: faire correspondre les fichiers qui ont cet ensemble complet et exact d’permissions.
      • Mise en garde : GNU find et BSD find implémentent tous deux un préfixe non standard supplémentaire avec la logique des ensembles de bits d’autorisation spécifiés , mais le font avec une syntaxe incompatible :
        • BSD trouver: +
        • GNU find: / [2]
      • Par conséquent, évitez ces extensions si votre code doit être portable .
  • Les exemples ci-dessous illustrent des réponses portables à diverses questions centrées sur les fichiers.

Exemples de commandes centrées sur les fichiers

Remarque:

  • Les exemples suivants sont compatibles avec POSIX , ce qui signifie qu’ils doivent fonctionner dans toute implémentation compatible POSIX, y compris GNU find et BSD find; en particulier, cela nécessite:
    • N’utilise PAS les préfixes de mode non standard + ou / .
    • En utilisant les formulaires POSIX des primaires d’opérateur logique :
      • ! pour NOT (GNU find et BSD find permettent aussi -not ); notez que \! est utilisé dans les exemples pour protéger ! des expansions de l’histoire du shell
      • -a pour AND (trouver GNU et rechercher BSD permettent aussi -and )
      • -o pour OU (GNU find et BSD find permettent également -or )
  • Les exemples utilisent des modes symboliques , car ils sont plus faciles à lire et à mémoriser.
    • Avec le préfixe de mode - , les opérateurs = et + peuvent être utilisés indifféremment (par exemple, -u=x est équivalent à -u+x – sauf si vous appliquez -x plus tard, mais cela ne sert à rien).
    • Utilisez , pour joindre des modes partiels; La logique ET est implicite; Par exemple, -u=x,g=x signifie que l’utilisateur et le bit exécutable du groupe doivent être définis.
    • Les modes ne peuvent pas exprimer eux-mêmes une correspondance négative dans le sens de “correspondance seulement si ce bit n’est PAS défini”; vous devez utiliser une expression -perm distincte avec le primaire non ! .
  • Notez que les primaires de find (telles que -print ou -perm ; également appelées actions et tests dans GNU find) sont implicitement jointes à -a (AND logique), et que -o et éventuellement les parenthèses (échappé sous la forme \( et \) pour le shell) sont nécessaires pour implémenter la logique OR.
  • find -L ... au lieu de simplement find ... est utilisé pour faire correspondre les liens symboliques aux exécutables
    • -L indique que find -L à évaluer les cibles des liens symboliques au lieu des liens symboliques eux-mêmes; par conséquent, sans -L , -type f ignorerait complètement les liens symboliques.
 # 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 # (eg, /bin) and user-installed executables in _shared_ locations # (eg, /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 consortingved 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] Description de -executable from man find partir de GNU find 4.4.2:

Correspond aux fichiers qui sont exécutables et aux répertoires consultables (dans un sens de résolution de nom de fichier). Cela prend en compte les listes de contrôle d’access et autres artefacts d’permissions que le test -perm ignore. Ce test utilise l’appel système access (2) et peut donc être trompé par les serveurs NFS qui effectuent le mappage UID (ou root-squashing), car de nombreux systèmes implémentent l’access (2) au kernel du client et ne peuvent donc pas utiliser les informations de mappage UID contenues sur le serveur. Étant donné que ce test est basé uniquement sur le résultat de l’appel système access (2), il n’est pas garanti qu’un fichier pour lequel ce test réussit puisse être réellement exécuté.

[2] Les versions de GNU find antérieures à la version 4.5.12 autorisaient également le préfixe + , mais celui-ci était tout d’abord déconseillé et finalement supprimé, car la combinaison de + avec des modes symboliques donne probablement des résultats inattendus, interprétés comme un masque d’permissions exact . Si vous (a) exécutez une version antérieure à 4.5.12 et (b) uniquement des modes octaux , vous pouvez utiliser + avec GNU find et BSD find, mais ce n’est pas une bonne idée.

Vous pouvez utiliser l’ -executable test -executable :

 -executable Matches files which are executable and directories which are searchable (in a file name resolution sense). 

Afin d’avoir une autre possibilité 1 de trouver les fichiers exécutables par l’utilisateur actuel:

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

(la commande de test ici est celle trouvée dans PATH, très probablement /usr/bin/test , pas la commande intégrée).


1 -executable cette -executable si l’indicateur -executable de find n’est pas disponible! ceci est subtilement différent de la solution de -perm +111 .

Cela a fonctionné pour moi et pensé au partage …

 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 
 find . -executable -type f 

ne garantit pas vraiment que le fichier est exécutable, il trouvera les fichiers avec le bit d’exécution défini. Si tu fais

 chmod a+x image.jpg 

La recherche ci-dessus va penser que image.jpg est un exécutable même si c’est vraiment une image JPEG avec le bit d’exécution défini.

Je travaille généralement sur le problème avec ceci:

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

Si vous voulez que le find imprime réellement des informations sur les fichiers exécutables, vous pouvez faire quelque chose comme ceci:

 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 

Dans l'exemple ci-dessus, le chemin d'access complet du fichier se trouve dans le dernier champ et doit indiquer où vous le cherchez avec awk "NAME = $ (awk '{print $ NF}' <<< $ LINE)" si le nom du fichier était ailleurs Pour trouver la chaîne de sortie, vous devez remplacer "NF" par la position numérique correcte. Si votre séparateur n'est pas de l'espace, vous devez également dire à votre séparateur ce qu'il est.

C’est tellement ridicule que ce ne soit pas super facile … encore moins impossible . Hands up, je m’en remets à Apple / Spotlight …

mdfind 'kMDItemContentType=public.unix-executable'

Au moins ça marche!

Eh bien, la réponse facile serait: “vos fichiers exécutables sont dans les répertoires contenus dans votre variable PATH” mais cela ne trouverait pas vraiment vos fichiers exécutables et pourrait manquer beaucoup d’exécutables de toute façon.

Je ne sais pas grand chose sur Mac mais je pense que “mdfind” kMDItemContentType = public.unix-executable “” pourrait manquer des choses comme des scripts interprétés

Si cela vous convient de trouver des fichiers avec les bits exécutables définis (qu’ils soient réellement exécutables ou non), alors il est bon de le faire.

 find . -type f -perm +111 -print 

où pris en charge l’option “-executable” rendra un autre filtre regardant acl et d’autres artefacts d’permissions, mais techniquement, il n’est pas très différent de “-pemr +111”.

Peut-être qu’à l’avenir, find supportera “-magic” et vous permettra de chercher explicitement des fichiers avec un identifiant magique spécifique … mais vous devrez alors spécifier pour affiner tous les formats exécutables mag id.

Je ne suis pas au courant d’une solution facile techniquement correcte sur Unix.

J’avais le même problème et la réponse se trouvait dans le code source de dmenu : l’utilitaire le plus utilisé à cette fin. Vous pouvez comstackr les fichiers ‘stest.c’ et ‘arg.h’ et cela devrait fonctionner. Il y a une page de manuel pour l’utilisation, que je mets là pour plus de commodité:

 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)