Comment trouver la différence entre un fichier script et un fichier binaire?

11
$ ls -l /usr/bin
total 200732

-rwxr-xr-x 1 root   root     156344 Oct  4  2013 adb
-rwxr-xr-x 1 root   root       6123 Oct  8  2013 add-apt-repository
 list goes long ---------

Dans ce qui précède adbest un fichier binaire et add-apt-repositoryest un fichier de script.J'obtiens ces informations en consultant les fichiers via nautilus.Mais via la ligne de commande, je n'ai trouvé aucune différence.Je ne suis pas en mesure de prédire si un fichier est un fichier binaire ou un fichier script.

Alors, comment puis-je différencier les fichiers script et binaires via la ligne de commande?

Avinash Raj
la source

Réponses:

16

Utilisez simplement file:

$ file /usr/bin/add-apt-repository
/usr/bin/add-apt-repository: Python script, ASCII text executable
$ file /usr/bin/ab
/usr/bin/ab: ELF 64-bit LSB  shared object, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=569314a9c4458e72e4ac66cb043e9a1fdf0b55b7, stripped

Comme expliqué dans man file:

NAME
   file — determine file type

DESCRIPTION
 This manual page documents version 5.14 of the file command.

 file tests each argument in an attempt to classify it.  There are three
 sets of tests, performed in this order: filesystem tests, magic tests,
 and language tests.  The first test that succeeds causes the file type to
 be printed.

 The type printed will usually contain one of the words text (the file
 contains only printing characters and a few common control characters and
 is probably safe to read on an ASCII terminal), executable (the file con‐
 tains the result of compiling a program in a form understandable to some
 UNIX kernel or another), or data meaning anything else (data is usually
 “binary” or non-printable).  Exceptions are well-known file formats (core
 files, tar archives) that are known to contain binary data.  When adding
 local definitions to /etc/magic, make sure to preserve these keywords.
 Users depend on knowing that all the readable files in a directory have
 the word “text” printed.  Don't do as Berkeley did and change “shell
 commands text” to “shell script”.

Vous pouvez également utiliser une astuce pour l'exécuter directement sur le nom de l'exécutable dans votre $PATH:

$ file $(type -p add-apt-repository | awk '{print $NF}')
/usr/local/bin/add-apt-repository: Python script, ASCII text executable
$ file $(type -p ab | awk '{print $NF}')
/usr/bin/ab: ELF 64-bit LSB  shared object, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=569314a9c4458e72e4ac66cb043e9a1fdf0b55b7, stripped

Pour trouver le type de fichier de tous les exécutables que vous pouvez trouver dans les répertoires de votre $PATH, vous pouvez faire ceci:

find $(printf "$PATH" | sed 's/:/ /g') -type f | xargs file

Et pour exécuter filesur tous les fichiers dans un répertoire particulier ( /usr/bin, par exemple), il suffit de faire

file /usr/bin/*
terdon
la source
Mais nous devons exécuter filechaque fichier pour voir de quel type de fichier s'agit-il. Existe-t-il une méthode simple pour tous les fichiers?
Avinash Raj
3
@AvinashRaj pour tous les fichiers d'un répertoire donné? Faites-le file /usr/bin/*. Comme toute autre commande.
terdon
5

En fait, les différences entre celles-ci ne sont pas si grandes.

Sur un système Unix ou Linux typique, il y a moins de cinq vrais exécutables. Sur Ubuntu, ce sont /lib/ld-linux.so.2et /sbin/ldconfig.

Tout le reste marqué comme exécutable est exécuté via un interpréteur , pour lequel deux formats sont pris en charge:

  1. Les fichiers commençant par #!auront le nom de l'interpréteur entre ceci et le premier caractère de nouvelle ligne (c'est vrai, il n'y a aucune exigence que les "scripts" soient des fichiers texte).
  2. Les fichiers ELF ont un PT_INTERPsegment qui donne le chemin vers l'interpréteur (généralement /lib/ld-linux.so.2).

Lorsqu'un tel fichier est exécuté, le noyau trouve le nom de l'interpréteur et l'appelle à la place. Cela peut se produire récursivement, par exemple lorsque vous exécutez un script shell:

  1. Le noyau ouvre le script, trouve le #! /bin/shau début.
  2. Le noyau s'ouvre /bin/sh, trouve le PT_INTERPsegment pointant vers /lib/ld-linux.so.2.
  3. Le noyau s'ouvre /lib/ld-linux.so.2, constate qu'il n'a pas de PT_INTERPsegment, charge son segment de texte et le démarre, en passant le handle ouvert à /bin/shet la ligne de commande pour votre appel de script.
  4. ld-linux.so.2charge les segments de code /bin/sh, résout les références de bibliothèque partagée et démarre sa fonction principale
  5. /bin/sh puis rouvre le fichier de script et commence à l'interpréter ligne par ligne.

Du point de vue du noyau, la seule différence est que pour le fichier ELF, le descripteur de fichier ouvert est transmis plutôt que le nom du fichier; c'est surtout une optimisation. Que l'interprète décide ensuite de passer à un segment de code chargé à partir du fichier ou de l'interpréter ligne par ligne est uniquement décidé par l'interpréteur et principalement basé sur la convention.

Simon Richter
la source
De bonnes informations, mais pas vraiment une réponse à cette question.
OrangeDog
La réponse est Mu .
Simon Richter
1

La commande de fichier est excellente, mais pour un outil d'analyse plus professionnel, j'aimerais que vous essayiez le package TrID qui est un outil d'identification de fichier.

TrID est un utilitaire conçu pour identifier les types de fichiers à partir de leurs signatures binaires, et il est facile à utiliser.

Pour plus d'informations et le package, visitez: Site

nux
la source