97

プログラムを実行せずに、bashで実行可能かどうかを確認する最も簡単な方法は何でしょうか。少なくとも、ファイルに実行権があり、現在のシステムと同じアーキテクチャ(たとえば、Windows実行可能ファイルやサポートされていない別のアーキテクチャではなく、システムが32ビットの場合は64ビットではない...)であるかどうかを確認する必要があります。

4

7 に答える 7

130

さまざまなテスト演算子を見てください(これはテストコマンド自体用ですが、組み込みのBASHテストとTCSHテストはほぼ同じです)。

FILEが存在し、実行(または検索)権限が付与さ-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

ファイルのタイプを判別するには、 fileコマンドを試してください。出力を解析して、ファイルのタイプを正確に確認できます。Word'o警告file複数行が返される場合があります。これが私の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コマンドは、OSに応じて異なる出力を返します。ただし、この単語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

3つすべてで、単語executableとアーキテクチャ(、、、x86-64またはi386with SPARC)が表示され32-bitます。


補遺

どうもありがとうございました、それは行く方法のようです。これを答えとしてマークする前に、プログラムを実行できるかどうかを確認するために、「ファイル」に対してどのような種類のスクリプトシェルチェックを実行する必要があるか(つまり、どのような種類の解析)について教えてください。そのようなテストを一般的に行うのが難しすぎる場合は、少なくともそれが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

基本的に、私はテストを実行しています。それが成功した場合は、fileコマンドの出力に対してgrepを実行します。つまり、grep -q出力は出力されませんが、grepの終了コードを使用して、文字列が見つかったかどうかを確認してください。システムに時間がかからない場合はgrep -q、を試すことができますgrep "regex" > /dev/null 2>&1

この場合も、コマンドの出力はfileシステムごとに異なる可能性があるため、これらがシステムで機能することを確認する必要があります。また、実行可能ビットをチェックしています。ファイルがバイナリ実行可能ファイルであるが、実行可能ビットがオンになっていない場合、実行可能ではないと言います。これはあなたが望むものではないかもしれません。

于 2012-04-25T16:27:37.847 に答える
23

-xオペレーターがファイルとディレクトリを異ならないことに誰も気づいていないようです。

したがって、実行可能ファイルを正確にチェックするには、 [[ -f SomeFile && -x SomeFile ]]

于 2016-09-14T11:17:55.410 に答える
7

ファイル、ディレクトリ、シンボリックリンクのテスト

ここに示す解決策は、ディレクトリまたはシンボリックリンク(あるいはその両方)で失敗します。Linuxでは、次のコマンドを使用してファイル、ディレクトリ、およびシンボリックリンクをテストできます。

if [[ -f "$file" && -x $(realpath "$file") ]]; then .... fi

OS Xでは、homebrewを使用して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
于 2018-04-07T13:20:41.387 に答える
5

また、シンボリックリンクの-x演算子に誰も気づいていないようです。通常のファイル(実行可能ファイルとして分類されていない)へのシンボリックリンク(チェーン)はテストに失敗します。

于 2016-12-03T06:04:35.477 に答える
1

まず、UnixとLinuxでは、ディレクトリも含めてすべてがファイルであることを覚えておく必要があります。ファイルがコマンドとして実行される権限を持つためには、次の3つの条件を満たす必要があります。

  1. 通常のファイルである必要があります
  2. 読み取り許可が必要です
  3. 実行許可が必要です

したがって、これは次の方法で簡単に実行できます。

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

ファイルが通常のファイルへのシンボリックリンクである場合、testコマンドはlink-nameではなくターゲットで動作します。したがって、上記のコマンドは、ファイルをコマンドとして使用できるかどうかを区別します。realpathしたがって、最初にファイルreadlinkをこれらのバリアントに渡す必要はありません。

ファイルが現在のOSで実行できる場合、それは別の質問です。上記のいくつかの回答はすでにその可能性を示しているので、ここで繰り返す必要はありません。

于 2021-02-19T11:13:45.653 に答える
0

ACL_EXECUTEファイルがどこにあるかに関係なく、ファイル自体がアクセス許可セット(ユーザー、グループ、その他)のいずれかにビットセットされているかどうかをテストするには、次のようにします。e。noexecオプションを指定したtmpfsでも、を使用し アクセス 許可文字列を取得し、それに少なくとも1つの「x」文字が含まれているかどうかを確認します。stat -c '%A'

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

比較の右側の部分は、 execオプション*x*x*x*でマウントされたボリュームに配置されたときに、すべての種類のユーザーがファイルを実行できるかどうかを確認する など、より具体的なケースに合うように変更できます。

于 2020-03-18T11:47:18.130 に答える
0

これはそれほど明白ではないかもしれませんが、外部シェルプロセスなしで実行可能ファイルを適切に呼び出すために、実行可能ファイルをテストする必要がある場合があります。

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 $?
}

myscript.sh

#!/bin/bash

echo 123

return 123

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

Linuxの場合

> tkl_exec_inproc /bin/bash -c 'echo 123'
123
> tkl_exec_inproc ./myscript.sh
123
> echo $?
123
于 2020-04-04T07:15:19.163 に答える