101 votes

Vérifiez 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 devrait au moins vérifier si le fichier a des droits d'exécution, 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 en 32 bits, ...) que le système actuel.

1 votes

Je penserais soit ls -la [nom du fichier] ou stat [nom du fichier]

1 votes

Ni ls -la ni stat ne donnent d'informations sur l'architecture prise en charge, ce qui est en réalité la partie de la question qui m'intéresse le plus. J'ai rencontré une erreur parce qu'un exécutable n'avait pas été compilé pour mon architecture, et j'aimerais créer un script pour éviter cela à l'avenir.

2 votes

@bob: Avez-vous essayé de vérifier la sortie de file exécutée sur ces fichiers?

135voto

David W. Points 49436

Jetez un œil aux différents opérateurs de test (c'est pour la commande de test elle-même, mais les tests intégrés BASH et TCSH sont plus ou moins les mêmes).

Vous remarquerez que -x FICHIER signifie le FICHIER existe et la permission d'exécution (ou de recherche) est accordée.

Script BASH, Bourne, Ksh, Zsh

if [[ -x "$fichier" ]]
then
    echo "Le fichier '$fichier' est exécutable"
else
    echo "Le fichier '$fichier' n'est pas exécutable ou introuvable"
fi

Script TCSH ou CSH:

if ( -x "$fichier" ) then
    echo "Le fichier '$fichier' est exécutable"
else
    echo "Le fichier '$fichier' n'est pas exécutable ou introuvable"
endif

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

$ file /bin/ls    
/bin/ls: Mach-O binaire universel avec 2 architectures
/bin/ls (pour l'architecture x86_64) : Exécutable Mach-O 64 bits x86_64
/bin/ls (pour l'architecture i386) : Exécutable Mach-O i386

La commande file renvoie une sortie différente en fonction du système d'exploitation. Cependant, le mot exécutable apparaîtra dans les programmes exécutables, et généralement l'architecture apparaîtra aussi.

Comparez cela à ce que j'obtiens sur mon Linux :

$ file /bin/ls
/bin/ls: ELF exécutable LSB 64 bits, AMD x86-64, version 1 (SYSV), pour GNU/Linux 2.6.9, lié de manière dynamique (utilise des bibliothèques partagées), déstrippé

Et un Solaris :

$ file /bin/ls
/bin/ls: ELF exécutable MSB 32 bits SPARC Version 1, lié de manière dynamique, déstrippé

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


Addendum

Merci beaucoup, c'est la marche à suivre. Avant de marquer ceci comme ma réponse, pouvez-vous me guider sur le type de test de script shell que je devrais effectuer (c'est-à-dire, quel type de parsing) sur 'file' pour vérifier si je peux exécuter un programme ? Si un tel test est trop difficile à faire de manière générale, j'aimerais au moins vérifier s'il s'agit d'un exécutable linux ou osX (Mach-O)

De mémoire, vous pourriez faire quelque chose comme cela en BASH :

if [ -x "$fichier" ] && file "$fichier" | grep -q "Mach-O"
then
    echo "Il s'agit d'un fichier Mac exécutable"
elif [ -x "$fichier" ] && file "$fichier" | grep -q "GNU/Linux"
then
    echo "Il s'agit d'un fichier Linux exécutable"
elif [ -x "$fichier" ] && file "$fichier" | grep q "script shell"
then
    echo "Il s'agit d'un script shell exécutable"
elif [ -x "$fichier" ]
then
    echo "Ce fichier est simplement marqué comme exécutable, mais son type est un mystère"
else
    echo "Ce fichier n'est même pas marqué comme étant exécutable"
fi

Fondamentalement, je fais le test, puis si cela réussit, je fais un grep sur la sortie de la commande file. Le grep -q signifie ne pas imprimer de sortie, mais utiliser 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 file peut varier d'un système à l'autre, vous devrez donc vérifier que cela fonctionnera sur votre système. De plus, je vérifie le bit exécutable. Si un fichier est un exécutable binaire, mais que le bit exécutable n'est pas activé, je dirai qu'il n'est pas exécutable. Ce n'est peut-être pas ce que vous voulez.

0 votes

Est-ce que le shell Bourne a [[ ou juste [?

2 votes

@glennjackman Bourne shell n'a que [ qui est en réalité une commande externe, et non une commande intégrée de l'interpréteur de commandes. Il est généralement situé dans le répertoire /bin. C'est un alias de la commande test.

0 votes

Merci beaucoup, c'est apparemment la voie à suivre. Avant de marquer ceci comme ma réponse, pourriez-vous s'il vous plaît me guider sur quel type de script shell je devrais exécuter (c'est-à-dire, quel type d'analyse) sur 'file' afin de vérifier si je peux exécuter un programme ? Si un tel test est trop difficile à réaliser de manière générale, j'aimerais au moins vérifier s'il s'agit d'un exécutable Linux ou d'un exécutable osX (Mach-O).

23voto

osexp2003 Points 51

Il semble que personne n'ait remarqué que l'opérateur -x ne distingue pas les fichiers des répertoires.

Donc, pour vérifier précisément si un fichier est exécutable, vous pouvez utiliser [[ -f SomeFile && -x SomeFile ]]

7voto

pyrocrasty Points 557

Tester les fichiers, répertoires et liens symboliques

Les solutions données ici échouent soit sur les répertoires, soit sur les liens symboliques (ou les deux). Sur Linux, vous pouvez tester les 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éfinition d'une fonction isexec

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

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

Ou simplement

isexec() { [[ -f "$1" && -x $(realpath "$1") ]]; }

Ensuite, vous pouvez tester en utilisant :

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

0 votes

Ne voulez-vous pas dire return true au lieu de echo true ?

0 votes

@jan6 Oui, merci. J'ai probablement utilisé cette version pour les tests et oublié de la changer.

0 votes

Aussi, le oneliner manque un point-virgule avant le crochet de fin (au moins bash le demande, ]]; }, pas sûr comment vous avez raté celui-là) Et bien que cela ne change pas la fonctionnalité, vous n'avez même pas besoin des backticks dans la déclaration if :) (je suppose que cela le met en évidence différemment, aucune autre différence si les statuts de retour sont corrects)

5voto

Dick Guertin Points 37

Il semble aussi que personne n'a remarqué l'opérateur -x sur les liens symboliques. Un lien symbolique (chaîne) vers un fichier régulier (non classifié comme exécutable) échoue au test.

1voto

kvantour Points 11497

Tout d'abord, vous devez vous rappeler que dans Unix et Linux, tout est un fichier, même les répertoires. Pour qu'un fichier ait les droits d'être exécuté comme une commande, il doit satisfaire 3 conditions :

  1. Il doit être un fichier régulier
  2. Il doit avoir des autorisations de lecture
  3. Il doit avoir des autorisations d'exécution

Cela peut donc être fait simplement avec :

[ -f "${file}" ] && [ -r "${file}" ] && [ -x "${file}" ]

Si votre fichier est un lien symbolique vers un fichier régulier, la commande de test fonctionnera sur la cible et non sur le nom du lien. Donc, la commande ci-dessus fait la distinction entre si un fichier peut être utilisé comme commande ou non. Il n'est donc pas nécessaire de passer d'abord le fichier à realpath ou à readlink ou à l'une de ces variantes.

Si le fichier peut être exécuté sur le système d'exploitation actuel, c'est une question différente. Certaines réponses ci-dessus ont déjà indiqué certaines possibilités à cet égard, il n'est donc pas nécessaire de le répéter ici.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X