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?

0voto

Anton Samsonov Points 898

Pour tester si un fichier lui-même a le bit ACL_EXECUTE défini dans l'un des ensembles de permissions (utilisateur, groupe, autres) indépendamment de l'endroit où il se trouve, c'est-à-dire même sur un tmpfs avec l'option noexec, utilisez stat -c '%A' pour obtenir la chaîne de permission, puis vérifiez si elle contient au moins une lettre "x" :

if [[ "$(stat -c '%A' 'mon_fichier_exec')" == *'x'* ]] ; then
    echo 'A la permission d'exécution pour quelqu'un'
fi

La partie droite de la comparaison peut être modifiée pour s'adapter à des cas plus spécifiques, comme *x*x*x* pour vérifier si tous les types d'utilisateurs devraient être en mesure d'exécuter le fichier lorsqu'il est placé sur un volume monté avec l'option exec.

0voto

user2672125 Points 11

Cela peut ne pas être si évident, mais parfois il est nécessaire de tester l'exécutable pour l'appeler de manière appropriée sans processus shell externe :

fonction tkl_is_file_os_exec()
{
  [[ ! -x "$1" ]] && return 255

  local exec_header_bytes
  case "$OSTYPE" in
    cygwin* | msys* | mingw*)
      # ATTENTION :
      #   La version de bash 3.2+ peut nécessiter un chemin de fichier avec l'extension,
      #   sinon une erreur sera lancée : `bash: ...: Aucun fichier ou dossier de ce type`.
      #   Nous faisons donc une supposition pour éviter l'erreur.
      #
      {
        read -r -n 4 exec_header_bytes 2> /dev/null < "$1" ||
        {
          [[ -x "${1%.exe}.exe" ]] && read -r -n 4 exec_header_bytes 2> /dev/null < "${1%.exe}.exe"
        } ||
        {
          [[ -x "${1%.com}.com" ]] && read -r -n 4 exec_header_bytes 2> /dev/null < "${1%.com}.com"
        }
      } &&
      if [[ "${exec_header_bytes:0:3}" == $'MZ\x90' ]]; then
        # $'MZ\x90\00' pour bash version 3.2.42+
        # $'MZ\x90\03' pour bash version 4.0+
        [[ "${exec_header_bytes:3:1}" == $'\x00' || "${exec_header_bytes:3:1}" == $'\x03' ]] && return 0
      fi
    ;;
    *)
      read -r -n 4 exec_header_bytes < "$1"
      [[ "$exec_header_bytes" == $'\x7fELF' ]] && return 0
    ;;
  esac

  return 1
}

# exécute le script dans le processus shell en cas de script shell, sinon exécute comme d'habitude
fonction tkl_exec_inproc()
{
  if tkl_is_file_os_exec "$1"; then
    "$@"
  else
    . "$@"
  fi
  return $?
}

myscript.sh:

#!/bin/bash

echo 123

return 123

Sous Cygwin:

> tkl_exec_inproc /cygdrive/c/Windows/system32/cmd.exe /c 'echo 123'
123
> tkl_exec_inproc /cygdrive/c/Windows/system32/chcp.com 65001
Active code page: 65001
> tkl_exec_inproc ./myscript.sh
123
> echo $?
123

Sous Linux:

> tkl_exec_inproc /bin/bash -c 'echo 123'
123
> tkl_exec_inproc ./myscript.sh
123
> echo $?
123

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