如何检查命令是不是存在于 shell 脚本中? [复制]

     2023-03-15     288

关键词:

【中文标题】如何检查命令是不是存在于 shell 脚本中? [复制]【英文标题】:How can I check if a command exists in a shell script? [duplicate]如何检查命令是否存在于 shell 脚本中? [复制] 【发布时间】:2011-11-23 06:37:19 【问题描述】:

我正在编写我的第一个 shell 脚本。在我的脚本中,我想检查某个命令是否存在,如果不存在,请安装可执行文件。如何检查此命令是否存在?

if # Check that foobar command doesnt exist
then
    # Now install foobar
fi

【问题讨论】:

刚好碰到。我认为这是同一个问题:***.com/questions/592620/…,但它提供了更多细节。 @JerryTian 感谢您的链接 同样相关的是How to 'hash -r' and refresh all shells? 和When to rehash executables in $PATH with bash? 这不是“已经回答”,因为它询问的是 shell 脚本,这至少意味着 sh,而所提到的问题特定于 bash 【参考方案1】:

尝试使用type

type foobar

例如:

$ type ls
ls is aliased to `ls --color=auto'

$ type foobar
-bash: type: foobar: not found

这比which 更可取,原因如下:

    默认的which 实现仅支持显示所有选项的-a 选项,因此您必须找到支持别名的替代版本

    type 会准确告诉您正在查看的内容(无论是 Bash 函数、别名还是适当的二进制文件)。

    type 不需要子进程

    type 不能被二进制文件屏蔽(例如,在 Linux 机器上,如果您创建一个名为 which 的程序,该程序出现在真正的 which 之前的路径中,事情就很糟糕了。@另一方面,987654332@ 是一个内置的 shell(是的,一个下属无意中这样做了一次)。

【讨论】:

你能把它放在 if/else 语句的形式(不输出到控制台)吗? 而在某些自定义 Linux 上,没有 ''which'' 命令。【参考方案2】:

which <cmd>

如果适用于您的情况,另请参阅 options which supports 获取别名。

例子

$ which foobar
which: no foobar in (/usr/local/bin:/usr/bin:/cygdrive/c/Program Files (x86)/PC Connectivity Solution:/cygdrive/c/Windows/system32/System32/WindowsPowerShell/v1.0:/cygdrive/d/Program Files (x86)/Graphviz 2.28/bin:/cygdrive/d/Program Files (x86)/GNU/GnuPG
$ if [ $? -eq 0 ]; then echo "foobar is found in PATH"; else echo "foobar is NOT found in PATH, of course it does not mean it is not installed."; fi
foobar is NOT found in PATH, of course it does not mean it is not installed.
$

PS:请注意,并非所有已安装的内容都可能在 PATH 中。通常要检查是否“安装”了某些东西,会使用与操作系统相关的安装相关命令。例如。 rpm -qa | grep -i "foobar" 用于 RHEL。

【讨论】:

which 还有其他陷阱 我刚开始阅读 man type 以了解它如何更好。也许你可以在这里发布它来节省我一些时间.. :) which 的真正问题在于它是一个 external 命令,无法处理当前 shell 会话内部的细节,因为它对他们一无所知。 Check if a program exists from a Bash script 特别建议不要使用which 这里最好不要使用which,其他答案更安全【参考方案3】:

一般来说,这取决于您的 shell,但如果您使用 bash、zsh、ksh 或 sh(由 dash 提供),以下应该可以工作:

if ! type "$foobar_command_name" > /dev/null; then
  # install foobar here
fi

对于真正的安装脚本,您可能希望确保在存在别名foobar 的情况下type 不会成功返回。在 bash 中,您可以执行以下操作:

if ! foobar_loc="$(type -p "$foobar_command_name")" || [[ -z $foobar_loc ]]; then
  # install foobar here
fi

【讨论】:

我喜欢这个答案。我尽量不被我更喜欢的ivants形象所左右;) hmm...当我将其更改为 if ! type "foo" > /dev/null; 时,我会在屏幕上看到输出“myscript.sh: line 12: type: foo: not found”,但是,它似乎仍然存在工作,因为当我说if ! type "ls" > /dev/null; 时没有输出并且 if 语句没有被执行(因为它返回 true)。当命令不存在时如何使输出静音? 安德鲁,试试if ! type "foo" > /dev/null 2>&1; > /dev/null 2>&1&> /dev/null 相同 type 的手册页在我的发行版(Arch Linux)上非常糟糕。帮助文本更好,尽管只有一点点。 type: usage: type [-afptP] name [name ...] 。手册页将“选项”显示为“无”。【参考方案4】:

Check if a program exists from a Bash script 很好地涵盖了这一点。在任何 shell 脚本中,您最好运行 command -v $command_name 来测试是否可以运行 $command_name。在 bash 中,您可以使用 hash $command_name,它还会对任何路径查找的结果进行散列处理;如果您只想查看二进制文件(而不是函数等),则可以使用 type -P $binary_name

【讨论】:

【参考方案5】:

问题没有指定外壳,所以对于那些使用 fish(友好的交互式外壳)的人:

if command -v foo > /dev/null
  echo exists
else
  echo does not exist
end

为了基本的 POSIX 兼容性,我们使用 -v 标志,它是 --search-s 的别名。

【讨论】:

不适用于别名 @Herrgott 那是因为command -v/-s$PATH 中搜索。 fish中的别名是函数,函数在$fish_function_path中搜索。检查别名是否存在的许多方法,例如if alias | grep -w 'myalias' >/dev/null; echo ok; end. 这不是也执行命令吗? @AaronFranke 它只搜索可执行文件,不执行它。 您可以使用--query 并避免重定向:fishshell.com/docs/current/cmds/command.html。虽然不符合 POSIX,但 command 内置在 Fish 中。【参考方案6】:

五种方式,4种用于bash,1种用于zsh:

type foobar &> /dev/null hash foobar &> /dev/null command -v foobar &> /dev/null which foobar &> /dev/null (( $+commands[foobar] ))(仅限 zsh)

您可以将它们中的任何一个放在您的if 子句中。根据我的测试(https://www.topbug.net/blog/2016/10/11/speed-test-check-the-existence-of-a-command-in-bash-and-zsh/),bash 推荐第 1 和第 3 种方法,zsh 推荐第 5 种速度。

【讨论】:

Check if a program exists from a Bash script 特别建议不要使用which 还有 echo =foobar 在 zsh 中。请注意,您的 zsh 解决方案仅返回 true/false,但不打印路径名(如果存在)。如果foo 不存在,echo $commands[foo] 也不会返回非零值。有关在两个 shell 中都可以使用的功能,请参阅here 第五条命令在 macOS Catalina 中的 zsh 中不返回任何内容。 zsh 版本为zsh 5.7.1 (x86_64-apple-darwin19.0) @Raptor if 检查退出代码。【参考方案7】:

我在安装脚本中的一个功能正是为此而制作的

function assertInstalled() 
    for var in "$@"; do
        if ! which $var &> /dev/null; then
            echo "Install $var!"
            exit 1
        fi
    done

示例调用:

assertInstalled zsh vim wget python pip git cmake fc-cache

【讨论】:

注意:这会使 zsh 崩溃 只有在您在脚本之外调用它或获取脚本时才会崩溃。如果您这样做,请将出口 1 更改为返回 1 或其他一些错误代码。 Check if a program exists from a Bash script 特别建议不要使用which 我用过这个,但把which改成了command -v【参考方案8】:

一个在 bash 和 zsh 中都可以使用的函数:

# Return the first pathname in $PATH for name in $1
function cmd_path () 
  if [[ $ZSH_VERSION ]]; then
    whence -cp "$1" 2> /dev/null
  else  # bash
     type -P "$1"  # No output if not in $PATH
  fi

如果在$PATH 中找不到该命令,则返回非零值。

【讨论】:

如何使用 shell 脚本检查 MySQL 数据库中是不是存在表?

】如何使用shell脚本检查MySQL数据库中是不是存在表?【英文标题】:HowtocheckifatableexistsinaMySQLdatabaseusingshellscript?如何使用shell脚本检查MySQL数据库中是否存在表?【发布时间】:2017-12-0810:13:31【问题描述】:我正在尝试使用shell... 查看详情

检查 Bash shell 脚本中是不是存在输入参数

】检查Bashshell脚本中是不是存在输入参数【英文标题】:CheckexistenceofinputargumentinaBashshellscript检查Bashshell脚本中是否存在输入参数【发布时间】:2011-09-2220:48:51【问题描述】:我需要检查输入参数是否存在。我有以下脚本if["$1"-gt... 查看详情

检查命令的输出是不是包含 shell 脚本中的某个字符串

】检查命令的输出是不是包含shell脚本中的某个字符串【英文标题】:Checkingifoutputofacommandcontainsacertainstringinashellscript检查命令的输出是否包含shell脚本中的某个字符串【发布时间】:2013-05-3115:22:32【问题描述】:我正在编写一个... 查看详情

shell脚本判断文件是不是存在

参考技术A通过git命令统计出了我在某个分支上改动的所有文件列表(文件路径是以和git工作区根目录的相对路径保存的),写入了一个文件all.txt。但是,随即发现,这个列表中的某些文件是我在开发过程中新建,然后有删除的,... 查看详情

Perl LWP::Simple::getstore 如何检查文件是不是存在于目标目录中

】PerlLWP::Simple::getstore如何检查文件是不是存在于目标目录中【英文标题】:PerlLWP::Simple::getstoreHowtocheckifthefileexistsindestinationdirectoryPerlLWP::Simple::getstore如何检查文件是否存在于目标目录中【发布时间】:2011-08-1908:35:59【问题描述... 查看详情

如何检查环境变量是不是存在并获取其值? [复制]

】如何检查环境变量是不是存在并获取其值?[复制]【英文标题】:Howtocheckifanenvironmentvariableexistsandgetitsvalue?[duplicate]如何检查环境变量是否存在并获取其值?[复制]【发布时间】:2017-01-1019:26:55【问题描述】:我正在编写一个she... 查看详情

Shell如何检查文件中的一行中是不是存在模式

】Shell如何检查文件中的一行中是不是存在模式【英文标题】:ShellHowtocheckifapatternexistsinalineinfileShell如何检查文件中的一行中是否存在模式【发布时间】:2015-12-2014:07:56【问题描述】:我们如何检查文件中特定行号的行中是否存... 查看详情

如何检查 csh 脚本中是不是存在任何文件?

】如何检查csh脚本中是不是存在任何文件?【英文标题】:howtocheckexistenceofanyfileincshscript?如何检查csh脚本中是否存在任何文件?【发布时间】:2015-03-0501:42:15【问题描述】:为了检查我正在使用的csh脚本中是否存在任何文件if[-f... 查看详情

如何检查文档是不是存在于flutter中?

】如何检查文档是不是存在于flutter中?【英文标题】:Howtocheckifadocumentexistsinflutter?如何检查文档是否存在于flutter中?【发布时间】:2021-05-0720:36:23【问题描述】:IM试图确定一个文档是否存在。如果它存在,我想用streambuilder来... 查看详情

如何检查MySQL中是不是存在行? (即检查电子邮件是不是存在于 MySQL 中)

】如何检查MySQL中是不是存在行?(即检查电子邮件是不是存在于MySQL中)【英文标题】:HowtocheckifarowexistsinMySQL?(i.e.checkifusernameoremailexistsinMySQL)如何检查MySQL中是否存在行?(即检查电子邮件是否存在于MySQL中)【发布时间】:20... 查看详情

如何检查图片是不是存在于图库中?

】如何检查图片是不是存在于图库中?【英文标题】:HowtocheckifimageexistsinGalleryornot?如何检查图片是否存在于图库中?【发布时间】:2018-05-1904:21:03【问题描述】:在我的应用程序中,当用户在保存到gallery之前捕获图像。我想检... 查看详情

如何检查MySQL中是不是存在一行? (即检查电子邮件是不是存在于 MySQL 中)

】如何检查MySQL中是不是存在一行?(即检查电子邮件是不是存在于MySQL中)【英文标题】:HowtocheckifarowexistsinMySQL?(i.e.checkifanemailexistsinMySQL)如何检查MySQL中是否存在一行?(即检查电子邮件是否存在于MySQL中)【发布时间】:2020... 查看详情

如何从 Bash 脚本中检查程序是不是存在?

】如何从Bash脚本中检查程序是不是存在?【英文标题】:HowcanIcheckifaprogramexistsfromaBashscript?如何从Bash脚本中检查程序是否存在?【发布时间】:2010-10-1004:59:30【问题描述】:我将如何验证程序是否存在,以返回错误并退出或继... 查看详情

如何检查元素是不是存在于一组项目中?

】如何检查元素是不是存在于一组项目中?【英文标题】:HowcanIcheckifanelementexistsinaSetofitems?如何检查元素是否存在于一组项目中?【发布时间】:2011-06-0900:40:11【问题描述】:在Java中的if语句中,我如何检查对象是否存在于一... 查看详情

Java中如何检查文件是不是存在于目录中

】Java中如何检查文件是不是存在于目录中【英文标题】:HowtoCheckifaFileExistsinaDirectoryinJavaJava中如何检查文件是否存在于目录中【发布时间】:2020-08-2823:01:38【问题描述】:我想知道某个特定目录中是否已经有一个Java文件,特别... 查看详情

如何检查文件是不是存在于 C++ 中? [复制]

】如何检查文件是不是存在于C++中?[复制]【英文标题】:HowtocheckifafileexistsinC++?[duplicate]如何检查文件是否存在于C++中?[复制]【发布时间】:2020-03-2005:05:59【问题描述】:我想确定一个文件是否存在于C++11中我有以下代码:ifstr... 查看详情

如何检查用户是不是存在于 Firebase 中?

】如何检查用户是不是存在于Firebase中?【英文标题】:HowcanIcheckifuserexistsinFirebase?如何检查用户是否存在于Firebase中?【发布时间】:2019-01-0421:01:22【问题描述】:我终于在创建用户和登录和注销方面进行了身份验证。但是现在... 查看详情

如何在linux中检查目录是不是存在。? [复制]

】如何在linux中检查目录是不是存在。?[复制]【英文标题】:Howtocheckdirectoryexistornotinlinux.?[duplicate]如何在linux中检查目录是否存在。?[复制]【发布时间】:2012-02-0602:40:34【问题描述】:给定一个文件路径(例如/src/com/mot),我... 查看详情