lhu*_*ath 2813
POSIX兼容:
command -v <the_command>
Run Code Online (Sandbox Code Playgroud)
对于bash
特定环境:
hash <the_command> # For regular commands. Or...
type <the_command> # To check built-ins and keywords
Run Code Online (Sandbox Code Playgroud)
避免which
.它不仅是一个外部进程,你只是做了很少的事情(意味着内置hash
,type
或者command
更便宜),你也可以依靠内置实际做你想要的,而外部命令的效果可以很容易地从系统到系统.
为何关心?
which
这甚至不设置退出状态,这意味着if which foo
甚至不会在那里工作,并会始终报告foo
存在,即使它不(注意,有些POSIX炮弹似乎对这样做hash
太).which
做自定义和恶意的事情,比如更改输出甚至挂钩到包管理器.所以,不要使用which
.而是使用以下其中之一:
$ command -v foo >/dev/null 2>&1 || { echo >&2 "I require foo but it's not installed. Aborting."; exit 1; }
$ type foo >/dev/null 2>&1 || { echo >&2 "I require foo but it's not installed. Aborting."; exit 1; }
$ hash foo 2>/dev/null || { echo >&2 "I require foo but it's not installed. Aborting."; exit 1; }
Run Code Online (Sandbox Code Playgroud)
(次要注意:有些人会建议2>&-
相同2>/dev/null
但更短 - 这是不真实的. 2>&-
关闭FD 2会导致程序在尝试写入stderr时出错,这与成功写入并丢弃输出有很大不同(又危险!))
如果你的哈希爆炸是/bin/sh
那么你应该关心POSIX所说的. type
和hash
的退出代码不是非常好由POSIX定义的,并且hash
被认为是当所述命令不存在成功地退出(未与看到这种type
尚未). command
POSIX很好地定义了退出状态,因此最安全的可能是最安全的.
如果你的脚本使用bash
虽然POSIX规则真的不重要了两者type
并hash
成为完全安全的使用. type
现在有一个-P
只搜索PATH
并且hash
有副作用的命令的位置将被哈希(为了下次你使用它时更快的查找),这通常是一件好事,因为你可能检查它的存在,以便实际使用它.
举个简单的例子,这里有一个运行的函数gdate
,否则date
:
gnudate() {
if hash gdate 2>/dev/null; then
gdate "$@"
else
date "$@"
fi
}
Run Code Online (Sandbox Code Playgroud)
nyu*_*a7h 485
以下是检查命令是否存在$PATH
且可执行的可移植方法:
[ -x "$(command -v foo)" ]
Run Code Online (Sandbox Code Playgroud)
例:
if ! [ -x "$(command -v git)" ]; then
echo 'Error: git is not installed.' >&2
exit 1
fi
Run Code Online (Sandbox Code Playgroud)
需要执行可执行检查,因为如果找不到具有该名称的可执行文件,bash将返回非可执行文件$PATH
.
另请注意,如果先前存在与可执行文件同名的非可执行文件,则$PATH
dash会返回前者,即使后者将被执行.这是一个错误,违反了POSIX标准.[ 错误报告 ] [ 标准 ]
此外,如果您要查找的命令已被定义为别名,则此操作将失败.
Gre*_*egV 201
我同意lhunath不鼓励使用which
,他的解决方案对BASH用户完全有效.但是,为了更加便携,command -v
应使用:
$ command -v foo >/dev/null 2>&1 || { echo "I require foo but it's not installed. Aborting." >&2; exit 1; }
Run Code Online (Sandbox Code Playgroud)
Command command
符合POSIX标准,请参阅此处了解其规范:http://pubs.opengroup.org/onlinepubs/9699919799/utilities/command.html
注意:type
符合POSIX标准,但type -P
不是.
Jos*_*ter 87
我在.bashrc中定义了一个函数,使这更容易.
command_exists () {
type "$1" &> /dev/null ;
}
Run Code Online (Sandbox Code Playgroud)
这是一个如何使用它的例子(从我的.bash_profile
.)
if command_exists mvim ; then
export VISUAL="mvim --nofork"
fi
Run Code Online (Sandbox Code Playgroud)
dre*_*lax 75
这取决于您是否想知道它是否存在于$PATH
变量的某个目录中,或者您是否知道它的绝对位置.如果您想知道它是否在$PATH
变量中,请使用
if which programname >/dev/null; then
echo exists
else
echo does not exist
fi
Run Code Online (Sandbox Code Playgroud)
否则使用
if [ -x /path/to/programname ]; then
echo exists
else
echo does not exist
fi
Run Code Online (Sandbox Code Playgroud)
第/dev/null/
一个示例中的重定向会抑制which
程序的输出.
Rom*_*rio 35
扩展@ lhunath和@ GregV的答案,这里是那些想要轻松地将该检查放在if
语句中的人的代码:
exists()
{
command -v "$1" >/dev/null 2>&1
}
Run Code Online (Sandbox Code Playgroud)
以下是如何使用它:
if exists bash; then
echo 'Bash exists!'
else
echo 'Your system does not have Bash'
fi
Run Code Online (Sandbox Code Playgroud)
dmc*_*kee 20
尝试使用:
test -x filename
Run Code Online (Sandbox Code Playgroud)
要么
[ -x filename ]
Run Code Online (Sandbox Code Playgroud)
从条件表达式下的bash手册页:
Run Code Online (Sandbox Code Playgroud)-x file True if file exists and is executable.
dch*_*les 15
要使用hash
,如@lhunath表明,在bash脚本:
hash foo &> /dev/null
if [ $? -eq 1 ]; then
echo >&2 "foo not found."
fi
Run Code Online (Sandbox Code Playgroud)
此脚本运行hash
,然后检查最新命令的退出代码(存储在其中的值$?
)是否等于1
.如果hash
没有找到foo
,退出代码将是1
.如果foo
存在,退出代码将是0
.
&> /dev/null
重定向标准错误和标准输出,hash
以便它不会出现在屏幕上并将echo >&2
消息写入标准错误.
tod*_*dsm 12
它可以更简单,只需:
#!/usr/bin/env bash
set -x
# if local program 'foo' returns 1 (doesn't exist) then...
if ! type -P foo; then
echo 'crap, no foo'
else
echo 'sweet, we have foo!'
fi
Run Code Online (Sandbox Code Playgroud)
更改foo
为vi
以使其他条件触发。
注意:始终首先处理负面情况,例如 if !
. 最好给程序提供一切失败的机会;让测试变得超级简单 ;-)
Ant*_*nyC 11
-v
如果为<command>
要测试的 POSIX_BUILTINS 选项设置了命令,则命令可以正常工作,但如果没有,它可能会失败。(它对我有用多年,但我最近遇到了一个不起作用的地方。)
我发现以下内容更防故障:
test -x "$(which <command>)"
Run Code Online (Sandbox Code Playgroud)
因为它测试三件事:路径、存在和执行权限。
kei*_*sar 10
这里有很多选择,但我很惊讶没有快速的单线。这是我在脚本开头使用的:
[[ "$(command -v mvn)" ]] || { echo "mvn is not installed" 1>&2 ; exit 1; }
[[ "$(command -v java)" ]] || { echo "java is not installed" 1>&2 ; exit 1; }
Run Code Online (Sandbox Code Playgroud)
这是基于此处选择的答案和另一个来源。
我从来没有得到上述解决方案在我可以访问的盒子上工作.例如,已安装类型(执行更多操作).所以需要内置指令.这个命令对我有用:
if [ `builtin type -p vim` ]; then echo "TRUE"; else echo "FALSE"; fi
Run Code Online (Sandbox Code Playgroud)
检查多个依赖项并将状态通知给最终用户
for cmd in latex pandoc; do
printf '%-10s' "$cmd"
if hash "$cmd" 2>/dev/null; then
echo OK
else
echo missing
fi
done
Run Code Online (Sandbox Code Playgroud)
样本输出:
latex OK
pandoc missing
Run Code Online (Sandbox Code Playgroud)
调整10
到最大命令长度.不是自动的,因为我没有看到非冗长的POSIX方法:
如何在Bash中对齐空格分隔表的列?
如果你检查程序是否存在,你可能会在以后运行它.为什么不尝试首先运行它?
if foo --version >/dev/null 2>&1; then
echo Found
else
echo Not found
fi
Run Code Online (Sandbox Code Playgroud)
这是一个更值得信赖的检查程序运行,而不仅仅是查看PATH目录和文件权限.
另外,您可以从程序中获得一些有用的结果,例如它的版本.
当然缺点是某些程序可能很重要,有些程序没有--version
立即(并成功)退出的选项.
我想要回答同样的问题,但要在 Makefile 中运行。
install:
@if [[ ! -x "$(shell command -v ghead)" ]]; then \
echo 'ghead does not exist. Please install it.'; \
exit -1; \
fi
Run Code Online (Sandbox Code Playgroud)
hash foo 2>/dev/null
:适用于zsh,bash,dash和ash.
type -p foo
:它似乎与zsh,bash和ash(busybox)一起使用,但不是破折号(它解释-p
为参数).
command -v foo
:适用于zsh,bash,dash,但不适用于ash(busybox)(-ash: command: not found
).
还要注意的是builtin
不可用ash
和dash
.
zsh
仅,但对于脚本编写非常有用zsh
(例如,编写完成脚本时):
该zsh/parameter
模块可以访问内部哈希表等commands
。从man zshmodules
:
THE ZSH/PARAMETER MODULE\n The zsh/parameter module gives access to some of the internal hash ta\xe2\x80\x90\n bles used by the shell by defining some special parameters.\n\n\n[...]\n\n commands\n This array gives access to the command hash table. The keys are\n the names of external commands, the values are the pathnames of\n the files that would be executed when the command would be in\xe2\x80\x90\n voked. Setting a key in this array defines a new entry in this\n table in the same way as with the hash builtin. Unsetting a key\n as in `unset "commands[foo]"' removes the entry for the given\n key from the command hash table.\n\n
Run Code Online (Sandbox Code Playgroud)\n虽然它是一个可加载模块,但它似乎是默认加载的,只要zsh
不与--emulate
.
例子:
\nmartin@martin ~ % echo $commands[zsh]\n/usr/bin/zsh\n
Run Code Online (Sandbox Code Playgroud)\n要快速检查某个命令是否可用,只需检查该密钥是否存在于哈希中:
\nif (( ${+commands[zsh]} ))\nthen\n echo "zsh is available"\nfi\n
Run Code Online (Sandbox Code Playgroud)\n请注意,散列将包含$PATH
文件夹中的任何文件,无论它们是否可执行。为了绝对确定,您必须拨打电话stat
:
if (( ${+commands[zsh]} )) && [[ -x $commands[zsh] ]]\nthen\n echo "zsh is available"\nfi\n
Run Code Online (Sandbox Code Playgroud)\n
该which
命令可能有用。男人哪个
如果找到可执行文件,则返回 0;如果未找到或不可执行,则返回 1:
NAME
which - locate a command
SYNOPSIS
which [-a] filename ...
DESCRIPTION
which returns the pathnames of the files which would
be executed in the current environment, had its
arguments been given as commands in a strictly
POSIX-conformant shell. It does this by searching
the PATH for executable files matching the names
of the arguments.
OPTIONS
-a print all matching pathnames of each argument
EXIT STATUS
0 if all specified commands are
found and executable
1 if one or more specified commands is nonexistent
or not executable
2 if an invalid option is specified
Run Code Online (Sandbox Code Playgroud)
好处是which
它可以确定可执行文件在which
运行的环境中是否可用 - 它可以避免一些问题......
小智 5
如果可以,为什么不使用Bash builtins?
which programname
Run Code Online (Sandbox Code Playgroud)
...
type -P programname
Run Code Online (Sandbox Code Playgroud)
对于那些感兴趣的人来说,如果您希望检测已安装的库,以前的答案中的任何方法都不起作用。我想您要么需要物理检查路径(可能是头文件等),要么像这样(如果您使用的是基于 Debian 的发行版):
dpkg --status libdb-dev | grep -q not-installed
if [ $? -eq 0 ]; then
apt-get install libdb-dev
fi
Run Code Online (Sandbox Code Playgroud)
从上面可以看出,查询结果为“0”意味着该软件包未安装。这是“grep”的函数 - “0”表示找到匹配项,“1”表示未找到匹配项。
归档时间: |
|
查看次数: |
618488 次 |
最近记录: |