Bash 检查文件是否可执行

Bash 检查文件是否可执行,bash,tcsh,Bash,Tcsh,我想知道在不执行程序的情况下,用bash检查程序是否可执行的最简单方法是什么?它至少应该检查文件是否具有执行权限,并且是否与当前系统具有相同的体系结构(例如,不是windows可执行文件或其他不受支持的体系结构,如果系统为32位,…),则不是64位。查看各种操作符(这是针对test命令本身的,但是内置BASH和TCSH测试或多或少是相同的) 您会注意到,-x FILE表示文件存在,并授予执行(或搜索)权限 BASH、Bourne、Ksh、Zsh脚本 if [[ -x "$file" ]] the

我想知道在不执行程序的情况下,用bash检查程序是否可执行的最简单方法是什么?它至少应该检查文件是否具有执行权限,并且是否与当前系统具有相同的体系结构(例如,不是windows可执行文件或其他不受支持的体系结构,如果系统为32位,…),则不是64位。

查看各种操作符(这是针对test命令本身的,但是内置BASH和TCSH测试或多或少是相同的)

您会注意到,
-x FILE
表示文件存在,并授予执行(或搜索)权限

BASH、Bourne、Ksh、Zsh脚本

if [[ -x "$file" ]]
then
    echo "File '$file' is executable"
else
    echo "File '$file' is not executable or found"
fi
TCSH或CSH脚本:

if ( -x "$file" ) then
    echo "File '$file' is executable"
else
    echo "File '$file' is not executable or found"
endif
若要确定文件的类型,请尝试该命令。您可以分析输出以查看文件的确切类型。Word'o Warning:有时
文件将返回多行。下面是在我的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
file
命令根据操作系统返回不同的输出。但是,单词
executable
将出现在可执行程序中,并且通常也会出现架构

将以上内容与我在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), stripped
和一个Solaris框:

$ file /bin/ls
/bin/ls:        ELF 32-bit MSB executable SPARC Version 1, dynamically linked, stripped
在这三个版本中,您将看到单词
executable
和体系结构(
x86-64
i386
,或
SPARC
32位


补遗
非常感谢,这似乎是正确的做法。在我将此标记为我的答案之前,请您指导我必须执行哪种脚本shell检查(即,哪种解析)为了检查我是否可以执行一个程序?如果这样的测试在一般情况下太难进行,我至少想检查它是linux可执行文件还是osX(Mach-O)

在我脑海中,你可以在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
基本上,我正在运行测试,如果测试成功,我会对
文件的输出执行grep。
grep-q
意味着不打印任何输出,而是使用grep的退出代码查看是否找到字符串。如果您的系统没有执行
grep-q
,您可以尝试
grep“regex”>/dev/null 2>&1


同样地,
file
命令的输出可能因系统而异,因此您必须验证这些命令是否能在您的系统上工作。此外,我正在检查可执行位。如果文件是二进制可执行文件,但可执行位未打开,我会说它不可执行。这可能不是您想要的。

似乎没有人注意到
-x
运算符不区分文件和目录

因此,要精确检查可执行文件,可以使用

[[-f SomeFile&&-x SomeFile]]

似乎也没有人注意到-符号链接上的x运算符。常规文件(未分类为可执行文件)的符号链接(链)测试失败。

测试文件、目录和符号链接 此处给出的解决方案在目录或符号链接(或两者)上都失败。在Linux上,您可以使用以下方法测试文件、目录和符号链接:

if [[ -f "$file" && -x $(realpath "$file") ]]; then .... fi
在OS X上,您应该能够使用自制软件安装coreutils并使用
grealpath

定义
isexec
函数 为了方便起见,可以定义函数:

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

isexec() { [[ -f "$1" && -x $(realpath "$1") ]]; }
然后,您可以使用以下方法进行测试:

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

要测试文件本身是否在任何权限集中(用户、组、其他人)设置了
ACL\u EXECUTE
位,而不管它位于何处,即即使在tmpfs上,使用noexec选项,使用
stat-c“%a”
获取权限字符串,然后检查它是否至少包含一个“x”字母:

if [[ "$(stat -c '%A' 'my_exec_file')" == *'x'* ]] ; then
    echo 'Has executable permission for someone'
fi

比较的右侧部分可能会被修改以适应更具体的情况,例如
*x*x*x*
,以检查当文件放置在安装了exec选项的卷上时,是否所有类型的用户都应该能够执行该文件。

这可能不是很明显,但有时需要测试可执行文件是否正确不使用外部shell进程调用它:

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

  local exec_header_bytes
  case "$OSTYPE" in
    cygwin* | msys* | mingw*)
      # CAUTION:
      #   The bash version 3.2+ might require a file path together with the extension,
      #   otherwise will throw the error: `bash: ...: No such file or directory`.
      #   So we make a guess to avoid the error.
      #
      {
        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' for bash version 3.2.42+
        # $'MZ\x90\03' for 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
}

# executes script in the shell process in case of a shell script, otherwise executes as usual
function tkl_exec_inproc()
{
  if tkl_is_file_os_exec "$1"; then
    "$@"
  else
    . "$@"
  fi
  return $?
}
在Cygwin中

#!/bin/bash

echo 123

return 123
> 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
> tkl_exec_inproc /bin/bash -c 'echo 123'
123
> tkl_exec_inproc ./myscript.sh
123
> echo $?
123
在Linux中

#!/bin/bash

echo 123

return 123
> 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
> tkl_exec_inproc /bin/bash -c 'echo 123'
123
> tkl_exec_inproc ./myscript.sh
123
> echo $?
123

首先,您需要记住,在Unix和Linux中,所有内容都是文件,甚至是目录。要使文件具有作为命令执行的权限,它需要满足3个条件:

  • 它需要是一个常规文件
  • 它需要有读取权限
  • 它需要有执行权限
  • 因此,这可以通过以下简单方法实现:

    [ -f "${file}" ] && [ -r "${file}" ] && [ -x "${file}" ]
    
    如果您的文件是指向常规文件的符号链接,则测试命令将对目标而不是链接名称进行操作。因此,上面的命令区分文件是否可用作命令。因此,无需首先将文件传递给
    realpath
    readlink
    或任何这些变体


    如果文件可以在当前操作系统上执行,这是一个不同的问题。上面的一些答案已经指出了一些可能性,因此无需在此重复。

    我认为ls-la[filename]或stat[filename]ls-la和stat都没有提供有关支持的体系结构的信息,这实际上是我最感兴趣的问题的一部分。我遇到了一个错误,因为没有为我的体系结构编译可执行文件,我想创建一个脚本以避免将来出现这种情况。@bob:您是否尝试过检查
    文件
    r的输出取消对这些文件的访问?@FatalError如何解析文件输出以检查可执行文件是否符合我的体系结构?检查:Bourne shell是否有
    [[
    或只是
    [
    ?@glennjackman Bourne shell只有
    [
    这实际上是一个外部命令,而不是shell的内置命令。它通常位于
    /bin
    目录中。它是
    test
    命令的别名。非常感谢,这似乎是一种方式。在我将此标记为我的答案之前,请您指导我使用什么类型的