bash 检测可执行文件是否在用户的 PATH 上
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6569478/
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
Detect if executable file is on user's PATH
提问by Dónal
In a bash script, I need to determine whether an executable named foo
is on the PATH.
在 bash 脚本中,我需要确定命名的可执行文件foo
是否在 PATH 上。
采纳答案by Michael Aaron Safyan
You can use which
:
您可以使用which
:
path_to_executable=$(which name_of_executable)
if [ -x "$path_to_executable" ] ; then
echo "It's here: $path_to_executable"
fi
回答by trevor
You could also use the Bash builtin type -P
:
您还可以使用 Bash 内置type -P
:
help type
cmd=ls
[[ $(type -P "$cmd") ]] && echo "$cmd is in PATH" ||
{ echo "$cmd is NOT in PATH" 1>&2; exit 1; }
回答by Tom Hale
TL;DR:
特尔;博士:
In bash
:
在bash
:
function is_bin_in_path {
builtin type -P "" &> /dev/null
}
Example usage of is_bin_in_path
:
示例用法is_bin_in_path
:
% is_bin_in_path ls && echo "in path" || echo "not in path"
in path
In zsh
:
在zsh
:
Use whence -p
instead.
使用whence -p
来代替。
For a version that works in both {ba,z}sh
:
对于适用于两者的版本{ba,z}sh
:
# True if is an executable in $PATH
# Works in both {ba,z}sh
function is_bin_in_path {
if [[ -n $ZSH_VERSION ]]; then
builtin whence -p "" &> /dev/null
else # bash:
builtin type -P "" &> /dev/null
fi
}
Non-solutions to avoid
避免的非解决方案
This is not a short answer because the solution must correctly handle:
这不是一个简短的答案,因为解决方案必须正确处理:
- Functions
- Aliases
- Builtin commands
- Reserved words
- 职能
- 别名
- 内置命令
- 保留字
Examples which failwith plain type
(note the token after type
changes):
以普通方式失败的示例type
(注意type
更改后的令牌):
$ alias foo=ls
$ type foo && echo "in path" || echo "not in path"
foo is aliased to `ls'
in path
$ type type && echo "in path" || echo "not in path"
type is a shell builtin
in path
$ type if && echo "in path" || echo "not in path"
if is a shell keyword
in path
Note that in bash
, which
is nota shell builtin (it is in zsh
):
需要注意的是在bash
,which
是不是一个shell内建(它是zsh
):
$ PATH=/bin
$ builtin type which
which is /bin/which
This answersays why to avoid using which
:
这个答案说明了为什么要避免使用which
:
Avoid
which
. Not only is it an external process you're launching for doing very little (meaning builtins likehash
,type
orcommand
are way cheaper), you can also rely on the builtins to actually do what you want, while the effects of external commands can easily vary from system to system.Why care?
- Many operating systems have a
which
that doesn't even set an exit status, meaning theif which foo
won't even work there and will alwaysreport thatfoo
exists, even if it doesn't (note that some POSIX shells appear to do this forhash
too).- Many operating systems make
which
do custom and evil stuff like change the output or even hook into the package manager.
避免
which
。它不仅是您启动的外部进程做的很少(意味着内置程序hash
,type
或者command
更便宜),您还可以依靠内置程序来实际执行您想要的操作,而外部命令的效果很容易从系统到系统。为什么要关心?
- 许多操作系统有
which
这甚至不设置退出状态,这意味着if which foo
甚至不会在那里工作,并会始终报告foo
存在,即使它没有(注意,一些POSIX炮弹似乎对这样做hash
太)。- 许多操作系统都会
which
做一些自定义的和邪恶的事情,比如更改输出甚至挂接到包管理器。
In this case, also avoid command -v
在这种情况下,也要避免 command -v
The answer I just quoted from suggests using command -v
, however this doesn't apply to the current "is the executable in $PATH
?" scenario: it will failin exactly the ways I've illustrated with plain type
above.
我刚刚引用的答案建议使用command -v
,但这不适用于当前的“可执行文件是否在$PATH
?” 场景:它会以我在上面简单说明的方式完全失败type
。
Correct solutions
正确的解决方案
In bash
we need to use type -P
:
在bash
我们需要使用type -P
:
-P force a PATH search for each NAME, even if it is an alias, builtin, or function, and returns the name of the disk file that would be executed
-P force a PATH search for each NAME, even if it is an alias, builtin, or function, and returns the name of the disk file that would be executed
In zsh
we need to use whence -p
:
在zsh
我们需要使用whence -p
:
-p Do a path search for name even if it is an alias, reserved word, shell function or builtin.
-p Do a path search for name even if it is an alias, reserved word, shell function or builtin.
回答by Eugene Yarmash
You can use the command
builtin, which is POSIX compatible:
您可以使用与command
POSIX 兼容的内置函数:
if [ -x "$(command -v "$cmd")" ]; then
echo "$cmd is in $PATH"
fi
The executable check is needed because command -v
detects functions and aliases as well as executables.
可执行检查是必需的,因为command -v
检测函数和别名以及可执行文件。
In Bash, you can also use type
with the -P
option, which forces a PATH
search:
在 Bash 中,您还可以使用强制搜索type
的-P
选项PATH
:
if type -P "$cmd" &>/dev/null; then
echo "$cmd is in $PATH"
fi
As already mentioned in the comments, avoid which
as it requires launching an external process and might give you incorrect output in some cases.
正如评论中已经提到的,避免,which
因为它需要启动外部进程,并且在某些情况下可能会给您不正确的输出。
回答by asev69
if command -v foo ; then foo ; else echo "foo unavailable" ; fi
如果命令 -v foo ; 然后 foo ; 否则 echo "foo 不可用" ; 菲
回答by HelloGoodbye
We can define a function for checking whether as executable exists by using which
:
我们可以定义一个函数来检查是否存在可执行文件which
:
function is_executable() {
which "$@" &> /dev/null
}
The function is called just like you would call an executable. "$@"
ensures that which
gets exactly the same arguments as are given to the function.
调用函数就像调用可执行文件一样。"$@"
确保which
获得与提供给函数的参数完全相同的参数。
&> /dev/null
ensures that whatever is written to stdout or stderr by which
is redirected to the null device (which is a special device which discards the information written to it) and not written to stdout or stderr by the function.
&> /dev/null
确保写入 stdout 或 stderr 的任何内容都which
被重定向到空设备(这是一种丢弃写入其中的信息的特殊设备),而不是由函数写入 stdout 或 stderr。
Since the function doesn't explicitly return with an return code, when it does return, the exit code of the latest executed executable—which in this case is which
—will be the return code of the function. which
will exit with a code that indicates success if it is able to find the executable specified by the argument to the function, otherwise with an exit code that indicates failure. This behavior will automatically be replicated by is_executable
.
由于函数没有显式返回返回码,当它返回时,最新执行的可执行文件的退出码(在本例中是)which
将是函数的返回码。which
如果能够找到函数的参数指定的可执行文件,则将退出并显示成功代码,否则退出代码表明失败。此行为将由 自动复制is_executable
。
We can then use that function to conditionally do something:
然后我们可以使用该函数有条件地做一些事情:
if is_executable name_of_executable; then
echo "name_of_executable was found"
else
echo "name_of_executable was NOT found"
fi
Here, if
executes the command(s) written between it and then
—which in our case is is_executable name_of_executable
—and chooses the branch to execute based on the return code of the command(s).
在这里,if
执行写在它和之间的命令then
——在我们的例子中是is_executable name_of_executable
——并根据命令的返回码选择要执行的分支。
Alternatively, we can skip defining the function and use which
directly in the if
-statement:
或者,我们可以跳过定义函数并which
直接在 -if
语句中使用:
if which name_of_executable &> /dev/null; then
echo "name_of_executable was found"
else
echo "name_of_executable was NOT found"
fi
However, I think this makes the code slightly less readable.
但是,我认为这会使代码的可读性稍差。