bash 检查文件是否可执行
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10319652/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Check if a file is executable
提问by bob
I am wondering what's the easiest way to check if a program is executable with bash, without executing it ? It should at least check whether the file has execute rights, and is of the same architecture (for example, not a windows executable or another unsupported architecture, not 64 bits if the system is 32 bits, ...) as the current system.
我想知道检查程序是否可以用 bash 执行而不执行它的最简单方法是什么?它至少应该检查文件是否具有执行权限,并且与当前系统具有相同的体系结构(例如,不是 Windows 可执行文件或其他不受支持的体系结构,如果系统是 32 位,则不是 64 位,......)。
回答by David W.
Take a look at the various testoperators (this is for the test command itself, but the built-in BASH and TCSH tests are more or less the same).
看看各种测试操作符(这是针对测试命令本身的,但是内置的BASH和TCSH测试或多或少是一样的)。
You'll notice that -x FILE
says FILE exists and execute (or search) permission is granted.
你会发现,-x FILE
说FILE存在和执行(或搜索)授予许可。
BASH, Bourne, Ksh, Zsh Script
BASH、Bourne、Ksh、Zsh 脚本
if [[ -x "$file" ]]
then
echo "File '$file' is executable"
else
echo "File '$file' is not executable or found"
fi
TCSH or CSH Script:
TCSH 或 CSH 脚本:
if ( -x "$file" ) then
echo "File '$file' is executable"
else
echo "File '$file' is not executable or found"
endif
To determine the typeof file it is, try the filecommand. You can parse the output to see exactly what type of file it is. Word 'o Warning: Sometimes file
will return more than one line. Here's what happens on my Mac:
要确定文件的类型,请尝试使用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
The file
command returns different output depending upon the OS. However, the word executable
will be in executable programs, and usually the architecture will appear too.
该file
命令根据操作系统返回不同的输出。然而,这个词executable
会出现在可执行程序中,通常架构也会出现。
Compare the above to what I get on my Linux box:
将上述内容与我在 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
And a Solaris box:
和一个 Solaris 盒子:
$ file /bin/ls
/bin/ls: ELF 32-bit MSB executable SPARC Version 1, dynamically linked, stripped
In all three, you'll see the word executable
and the architecture (x86-64
, i386
, or SPARC
with 32-bit
).
在所有三个,你会看到这个词executable
和架构(x86-64
,i386
,或SPARC
用32-bit
)。
Addendum
附录
Thank you very much, that seems the way to go. Before I mark this as my answer, can you please guide me as to what kind of script shell check I would have to perform (ie, what kind of parsing) on 'file' in order to check whether I can execute a program ? If such a test is too difficult to make on a general basis, I would at least like to check whether it's a linux executable or osX (Mach-O)
非常感谢,这似乎是要走的路。在我将此标记为我的答案之前,您能否指导我了解我必须对“文件”执行哪种脚本外壳检查(即,哪种解析)以检查我是否可以执行程序?如果这样的测试在一般基础上很难进行,我至少想检查它是 linux 可执行文件还是 osX (Mach-O)
Off the top of my head, you could do something like this in BASH:
在我的脑海里,你可以在 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
Basically, I'm running the test, then if that is successful, I do a grep on the output of the file
command. The grep -q
means don't print any output, but use the exit code of grep to see if I found the string. If your system doesn't take grep -q
, you can try grep "regex" > /dev/null 2>&1
.
基本上,我正在运行测试,然后如果测试成功,我会对file
命令的输出执行 grep 。这grep -q
意味着不打印任何输出,而是使用 grep 的退出代码来查看是否找到了字符串。如果你的系统不支持grep -q
,你可以试试grep "regex" > /dev/null 2>&1
。
Again, the output of the file
command may vary from system to system, so you'll have to verify that these will work on your system. Also, I'm checking the executable bit. If a file is a binary executable, but the executable bit isn't on, I'll say it's not executable. This may not be what you want.
同样,file
命令的输出可能因系统而异,因此您必须验证这些命令是否适用于您的系统。另外,我正在检查可执行位。如果一个文件是二进制可执行文件,但可执行位没有打开,我会说它不是可执行文件。这可能不是您想要的。
回答by osexp2003
Seems nobody noticed that -x
operator does not differ file with directory.
似乎没有人注意到-x
操作员没有将文件与目录不同。
So to precisely check an executable file, you may use
[[ -f SomeFile && -x SomeFile ]]
因此,要精确检查可执行文件,您可以使用
[[ -f SomeFile && -x SomeFile ]]
回答by Dick Guertin
Also seems nobody noticed -x operator on symlinks. A symlink (chain) to a regular file (not classified as executable) fails the test.
似乎也没有人注意到符号链接上的 -x 运算符。到常规文件(未归类为可执行文件)的符号链接(链)未通过测试。
回答by pyrocrasty
Testing files, directories and symlinks
测试文件、目录和符号链接
The solutions given here fail on either directories or symlinks (or both). On Linux, you can test files, directories and symlinks with:
此处给出的解决方案在目录或符号链接(或两者)上都失败。在 Linux 上,您可以使用以下命令测试文件、目录和符号链接:
if [[ -f "$file" && -x $(realpath "$file") ]]; then .... fi
On OS X, you should be able to install coreutils with homebrew and use grealpath
.
在 OS X 上,您应该能够使用自制软件安装 coreutils 并使用grealpath
.
Defining an isexec
function
定义isexec
函数
You can define a function for convenience:
为方便起见,您可以定义一个函数:
isexec() {
if [[ -f "" && -x $(realpath "") ]]; then
true;
else
false;
fi;
}
Or simply
或者干脆
isexec() { [[ -f "" && -x $(realpath "") ]]; }
Then you can test using:
然后您可以使用以下方法进行测试:
if `isexec "$file"`; then ... fi
回答by Anton Samsonov
To?test whether a?file itself has ACL_EXECUTE
bit set in?any of?permission sets (user, group, others) regardless of?where it resides, i.?e. even on?a?tmpfswith?noexecoption, use stat -c '%A'
to?get the?permission string and?then check if it contains at?least a?single “x” letter:
测试文件本身是否ACL_EXECUTE
在任何权限集(用户、组、其他)中设置了位,而不管它驻留在何处,即 即使在?a?tmpfs与?noexec选项,用于stat -c '%A'
获取权限字符串然后检查它是否包含至少一个“x”字母:
if [[ "$(stat -c '%A' 'my_exec_file')" == *'x'* ]] ; then
echo 'Has executable permission for someone'
fi
The?right-hand part of?comparison may be modified to?fit more specific cases, such?as *x*x*x*
to?check whether all kinds of?users should be able to?execute the?file when it is placed on?a?volume mounted with?execoption.
比较的右侧部分可以修改以适应更具体的情况,例如*x*x*x*
检查所有类型的用户是否应该能够在将文件放置在卷挂载上时执行该文件和?执行选项。
回答by Andry
This might be not so obvious, but sometime is required to test the executable to appropriately call it without an external shell process:
这可能不是那么明显,但有时需要测试可执行文件以在没有外部 shell 进程的情况下正确调用它:
function tkl_is_file_os_exec()
{
[[ ! -x "" ]] && 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 < "" ||
{
[[ -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#!/bin/bash
echo 123
return 123
' for bash version 3.2.42+
# $'MZ\x90' 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 < ""
[[ "$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 ""; then
"$@"
else
. "$@"
fi
return $?
}
myscript.sh:
我的脚本.sh:
> 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
In Cygwin:
在 Cygwin 中:
> tkl_exec_inproc /bin/bash -c 'echo 123'
123
> tkl_exec_inproc ./myscript.sh
123
> echo $?
123
In Linux:
在 Linux 中:
##代码##