Vérifier si un fichier est exécutable

Je me demande quel est le moyen le plus simple de vérifier si un programme est exécutable avec bash, sans l’exécuter? Il doit au moins vérifier si le fichier a des droits d’exécution et est de la même architecture (par exemple, pas un exécutable Windows ou une autre architecture non prise en charge, pas 64 bits si le système est 32 bits, …).

Consultez les différents opérateurs de test (ceci est pour la commande de test elle-même, mais les tests BASH et TCSH intégrés sont plus ou moins les mêmes).

Vous remarquerez que -x FILE indique que FILE existe et que l’autorisation d’exécution (ou de recherche) est accordée .

BASH, Bourne, Ksh, Script Zsh

 if [[ -x "$file" ]] then echo "File '$file' is executable" else echo "File '$file' is not executable or found" fi 

TCSH ou CSH Script:

 if ( -x "$file" ) then echo "File '$file' is executable" else echo "File '$file' is not executable or found" endif 

Pour déterminer le type de fichier, essayez la commande de fichier . Vous pouvez parsingr la sortie pour voir exactement quel type de fichier il s’agit. Word ‘o Avertissement : Parfois, le file renverra plus d’une ligne. Voici ce qui se passe sur mon Mac:

 $ file /bin/ls /bin/ls: Mach-O universal binary with 2 architectures /bin/ls (for architecture x86_64): Mach-O 64-bit executable x86_64 /bin/ls (for architecture i386): Mach-O executable i386 

La commande file renvoie une sortie différente selon le système d’exploitation. Cependant, le mot executable sera dans les programmes exécutables, et l’architecture apparaîtra généralement aussi.

Comparez ce qui précède à ce que j’obtiens sur ma boîte Linux:

 $ file /bin/ls /bin/ls: ELF 64-bit LSB executable, AMD x86-64, version 1 (SYSV), for GNU/Linux 2.6.9, dynamically linked (uses shared libs), ssortingpped 

Et une boîte Solaris:

 $ file /bin/ls /bin/ls: ELF 32-bit MSB executable SPARC Version 1, dynamically linked, ssortingpped 

Dans les trois cas, vous verrez le mot executable et l’architecture ( x86-64 , i386 ou SPARC avec 32-bit ).


Addenda

Merci beaucoup, cela semble être la voie à suivre. Avant de marquer ma réponse, pouvez-vous me guider sur le type de vérification de script que je devrai effectuer (c.-à-d. Quel type d’parsing) sur «fichier» pour vérifier si je peux exécuter un programme? Si un tel test est trop difficile à réaliser sur une base générale, je voudrais au moins vérifier si c’est un exécutable linux ou osX (Mach-O)

header, tu pourrais faire quelque chose comme ça dans BASH:

 if [ -x "$file" ] && file "$file" | grep -q "Mach-O" then echo "This is an executable Mac file" elif [ -x "$file" ] && file "$file" | grep -q "GNU/Linux" then echo "This is an executable Linux File" elif [ -x "$file" ] && file "$file" | grep q "shell script" then echo "This is an executable Shell Script" elif [ -x "$file" ] then echo "This file is merely marked executable, but what type is a mystery" else echo "This file isn't even marked as being executable" fi 

Fondamentalement, je lance le test, si cela réussit, je fais un grep sur la sortie de la commande de file . Le grep -q signifie que vous n’imprimez aucune sortie, mais utilisez le code de sortie de grep pour voir si j’ai trouvé la chaîne. Si votre système ne prend pas grep -q , vous pouvez essayer grep "regex" > /dev/null 2>&1 .

Encore une fois, la sortie de la commande de file peut varier d’un système à l’autre, vous devrez donc vérifier qu’ils fonctionneront sur votre système. Aussi, je vérifie le bit exécutable. Si un fichier est un exécutable binary, mais que le bit exécutable n’est pas activé, je dirai que ce n’est pas exécutable. Ce n’est peut-être pas ce que vous voulez.

Semble que personne n’a remarqué que l’opérateur -x ne diffère pas du fichier avec le répertoire.

Donc, pour vérifier avec précision un fichier exécutable, vous pouvez utiliser [[ -f SomeFile && -x SomeFile ]]

Il semble également que personne n’ait remarqué l’opérateur -x sur les liens symboliques. Un lien symbolique (chaîne) vers un fichier normal (non classé comme exécutable) échoue au test.

Test de fichiers, répertoires et liens symboliques

Les solutions données ici échouent sur les répertoires ou les liens symboliques (ou les deux). Sous Linux, vous pouvez tester des fichiers, répertoires et liens symboliques avec:

 if [[ -f "$file" && -x $(realpath "$file") ]]; then .... fi 

Sous OS X, vous devriez pouvoir installer coreutils avec homebrew et utiliser grealpath .

Définir une fonction isexec

Vous pouvez définir une fonction pour plus de commodité:

 isexec() { if [[ -f "$1" && -x $(realpath "$1") ]]; then echo true; else echo false; fi; } 

Ensuite, vous pouvez tester en utilisant:

 if `isexec "$file"`; then ... fi