如何找到脚本文件和二进制文件之间的区别?

Avi*_*Raj 11 command-line files

$ 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 ---------
Run Code Online (Sandbox Code Playgroud)

上面adb是一个二进制文件,add-apt-repository是一个脚本文件。我通过nautilus查看文件得到了这个信息。但是通过命令行,我没有发现任何差异。我无法预测文件是二进制文件还是一个脚本文件。

那么如何通过命令行区分脚本文件和二进制文件呢?

ter*_*don 16

只需使用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
Run Code Online (Sandbox Code Playgroud)

如中所述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”.
Run Code Online (Sandbox Code Playgroud)

您还可以使用技巧直接在您的可执行文件的名称上运行它$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
Run Code Online (Sandbox Code Playgroud)

要查找可在您的 目录中找到的所有可执行文件的文件类型$PATH,您可以执行以下操作:

find $(printf "$PATH" | sed 's/:/ /g') -type f | xargs file
Run Code Online (Sandbox Code Playgroud)

并且要file在特定目录(/usr/bin例如)中的所有文件上运行,只需执行

file /usr/bin/*
Run Code Online (Sandbox Code Playgroud)

  • @AvinashRaj 用于给定目录中的所有文件?只需执行`file /usr/bin/*`。就像任何其他命令一样。 (3认同)

Sim*_*ter 6

实际上,它们之间的差异并没有那么大。

在典型的 Unix 或 Linux 系统上,真正的可执行文件少于五个。在 Ubuntu 上,这些是/lib/ld-linux.so.2/sbin/ldconfig

其他标记为可执行的所有内容都通过解释器运行,解释器支持两种格式:

  1. 以 开头的文件#!将在此字符和第一个换行符之间具有解释器名称(没错,“脚本”不要求是文本文件)。
  2. ELF 文件有一个PT_INTERP段,给出解释器的路径(通常是/lib/ld-linux.so.2)。

当这样一个文件被执行时,内核会找到解释器的名字,并调用它。这可能会递归发生,例如当您运行 shell 脚本时:

  1. 内核打开脚本,找到#! /bin/sh开头。
  2. 内核打开/bin/sh,找到PT_INTERP指向的段/lib/ld-linux.so.2
  3. 内核打开/lib/ld-linux.so.2,发现它没有PT_INTERP段,加载它的文本段并启动它,将打开的句柄传递/bin/sh给您的脚本调用的命令行。
  4. ld-linux.so.2从中加载代码段/bin/sh,解析共享库引用并启动其主要功能
  5. /bin/sh 然后重新打开脚本文件,并开始逐行解释它。

从内核的角度来看,唯一的区别是对于ELF文件,传递的是打开的文件描述符而不是文件名;这主要是一种优化。解释器然后决定跳转到从文件加载的代码段,还是逐行解释它仅由解释器决定,并且主要基于约定。