Мне интересно, какой самый простой способ проверить, является ли программа исполняемой с помощью bash, не выполняя ее? Он должен, по крайней мере, проверить, имеет ли файл права на выполнение и имеет ли он ту же архитектуру (например, не исполняемый файл Windows или другую неподдерживаемую архитектуру, а не 64-битную, если система 32-битная, ...), что и текущая система.
Проверить, является ли файл исполняемым
Ответы (7)
Взгляните на различные операторы test (это для самой команды 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
Чтобы определить тип файла, попробуйте команду file . Вы можете проанализировать вывод, чтобы точно определить тип файла. Word 'o Warning. Иногда 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
возвращает разные выходные данные в зависимости от ОС. Тем не менее, слово 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
И коробка Солярис:
$ file /bin/ls
/bin/ls: ELF 32-bit MSB executable SPARC Version 1, dynamically linked, stripped
Во всех трех вы увидите слово executable
и архитектуру (x86-64
, i386
или 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
По сути, я запускаю тест, затем, если он успешен, я делаю grep на выходе команды file
. grep -q
означает, что ничего не выводится, а используется код выхода grep, чтобы узнать, нашел ли я строку. Если ваша система не принимает grep -q
, вы можете попробовать grep "regex" > /dev/null 2>&1
.
Опять же, вывод команды file
может варьироваться от системы к системе, поэтому вам придется убедиться, что они будут работать в вашей системе. Кроме того, я проверяю исполняемый бит. Если файл является двоичным исполняемым файлом, но бит исполняемого файла не включен, я скажу, что он не является исполняемым. Это может быть не то, что вы хотите.
[[
или только [
?
- person glenn jackman; 25.04.2012
[
, которая на самом деле является внешней командой, а не встроенной в оболочку. Обычно он находится в каталоге /bin
. Это псевдоним команды test
.
- person David W.; 26.04.2012
file
уже делает. Он использует файл с именем магический файл (обычно /etc/magic
, но может варьироваться от системы к системе. См. man file
, чтобы найти местонахождение магического файла). Взгляните на волшебный файл, чтобы увидеть, что связано с обнаружением конкретного файла.
- person David W.; 30.04.2012
Кажется, никто не заметил, что оператор -x
не различает файл с каталогом.
Таким образом, чтобы точно проверить исполняемый файл, вы можете использовать
[[ -f SomeFile && -x SomeFile ]]
Тестирование файлов, каталогов и символических ссылок
Приведенные здесь решения не работают ни с каталогами, ни с символическими ссылками (или с обоими). В Linux вы можете тестировать файлы, каталоги и символические ссылки с помощью:
if [[ -f "$file" && -x $(realpath "$file") ]]; then .... fi
В OS X вы сможете установить coreutils с помощью homebrew и использовать 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
return true
вместо echo true
?
- person jan6; 26.01.2019
]]; }
, не знаю, как вы это пропустили). И хотя это не меняет функциональность, вам даже не нужны галочки в выражении if
:) (Я предполагаю, что это заставляет его выделяться по-другому, никакой другой разницы, если статусы возврата верны)
- person jan6; 02.02.2019
Также кажется, что никто не заметил оператора -x на символических ссылках. Символическая ссылка (цепочка) на обычный файл (не классифицируемый как исполняемый) не проходит тест.
Чтобы проверить, установлен ли для самого файла бит ACL_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. вариант.
Это может быть не так очевидно, но иногда требуется протестировать исполняемый файл, чтобы правильно вызвать его без внешнего процесса оболочки:
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
Во-первых, вам нужно помнить, что в Unix и Linux все является файлом, даже каталоги. Чтобы файл имел права на выполнение как команду, он должен удовлетворять трем условиям:
- Это должен быть обычный файл
- Он должен иметь права на чтение
- Он должен иметь права на выполнение
Итак, это можно сделать просто с помощью:
[ -f "${file}" ] && [ -r "${file}" ] && [ -x "${file}" ]
Если ваш файл является символической ссылкой на обычный файл, тестовая команда будет работать с целью, а не с именем ссылки. Таким образом, приведенная выше команда определяет, можно ли использовать файл в качестве команды или нет. Таким образом, нет необходимости сначала передавать файл realpath
или readlink
или любому из этих вариантов.
Если файл может быть выполнен на текущей ОС, это другой вопрос. Некоторые ответы выше уже указывали на некоторые возможности для этого, поэтому нет необходимости повторять это здесь.
file
для этих файлов? - person FatalError   schedule 25.04.2012