【问题标题】:How can check if particular application/software is installed in Mac OS如何检查特定应用程序/软件是否安装在 Mac OS 中
【发布时间】:2011-07-13 16:33:51
【问题描述】:

我想检查是否使用 Perl/Shell 脚本在 Mac OS 中安装了特定应用程序。 我正在使用 PackageMaker 编写包,我需要在安装应用程序之前检查用户机器上的几个应用程序。 所以我打算写一个脚本来帮我检查一下。 请建议我是否可以以更好的方式执行此操作。

【问题讨论】:

  • 也许在 /Applications 中寻找应用程序 .app 文件?
  • Applescript 可能是一个测试它是否可以启动应用程序的选项。不知道这是否违反了您的 perl/shell。
  • @JoePasq ,用户也可以在其他位置安装应用程序

标签: macos installation


【解决方案1】:

补充@Bavarious' helpful answer

以下是通用bash 函数,它们通过返回应用程序的路径或其捆绑包ID(如果已安装)来扩展测试是否安装了应用程序。如果您将它们放在您的 bash 配置文件中,它们也可能会在交互式使用中派上用场。

这两个函数仍然可以作为一个应用程序是否安装的测试;例如:
if ! whichapp 'someApp' &>/dev/null; then ... # not installed

这两个函数都不区分大小写,并且在指定 name 时,.app 后缀是可选的。 但是请注意,本地化名称是被识别的。

whichapp

通过任一捆绑ID 名称定位应用程序的功能。 如果找到,则返回应用程序的路径;否则报错。

例子:

  • whichapp finder # -> '/System/Library/CoreServices/Finder.app/'
  • whichapp com.apple.finder # -> '/System/Library/CoreServices/Finder.app/'

bundleid

给定应用程序的名称,返回其捆绑包 ID。

例子:

  • bundleid finder # -> 'com.apple.finder'

实现说明:在 AppleScript 代码中,很容易绕过 Finder 上下文并简单地使用例如application [id] <appNameOrBundleId>path to application [id] <appNameOrBundleId> 在全局上下文中,但问题是总是启动目标应用程序,这是不受欢迎的。

来源:哪个应用程序

whichapp() {
  local appNameOrBundleId=$1 isAppName=0 bundleId
  # Determine whether an app *name* or *bundle ID* was specified.
  [[ $appNameOrBundleId =~ \.[aA][pP][pP]$ || $appNameOrBundleId =~ ^[^.]+$ ]] && isAppName=1
  if (( isAppName )); then # an application NAME was specified
    # Translate to a bundle ID first.
    bundleId=$(osascript -e "id of application \"$appNameOrBundleId\"" 2>/dev/null) ||
      { echo "$FUNCNAME: ERROR: Application with specified name not found: $appNameOrBundleId" 1>&2; return 1; }
  else # a BUNDLE ID was specified
    bundleId=$appNameOrBundleId
  fi
    # Let AppleScript determine the full bundle path.
  fullPath=$(osascript -e "tell application \"Finder\" to POSIX path of (get application file id \"$bundleId\" as alias)" 2>/dev/null ||
    { echo "$FUNCNAME: ERROR: Application with specified bundle ID not found: $bundleId" 1>&2; return 1; })
  printf '%s\n' "$fullPath"
  # Warn about /Volumes/... paths, because applications launched from mounted
  # devices aren't persistently installed.
  if [[ $fullPath == /Volumes/* ]]; then
    echo "NOTE: Application is not persistently installed, due to being located on a mounted volume." >&2 
  fi
}

注意:该函数还会在给定会话中找到从已安装的卷启动的应用程序谢谢Wonder Dog,但既然这样应用程序未永久安装(未向 macOS 启动服务永久注册),在该事件中会发出 警告
如果需要,您可以轻松地修改函数以改为报告错误。

来源:bundleid

bundleid() {
  osascript -e "id of application \"$1\"" 2>/dev/null || 
    { echo "$FUNCNAME: ERROR: Application with specified name not found: $1" 1>&2; return 1; }
}

【讨论】:

  • 此方法还会列出垃圾箱中的应用程序或用于安装应用程序的已安装卷。我认为这些不应被视为“已安装”的应用程序。
  • @WonderDog:从已安装的卷中重新应用程序的好处:我已经修改了函数以在这种情况下报告警告,但如果需要,您可以轻松地将其更改为错误(或过滤掉 @ 987654335@ 事后匹配)。在 macOS 10.13.6 上,我没有看到有关已删除应用程序的症状 - 您使用的是什么版本?
【解决方案2】:

以下 bash 脚本使用 AppleScript 来检查是否安装了应用程序,基于 a solution by Michael Pilat

#!/bin/bash

APPLESCRIPT=`cat <<EOF
on run argv
  try
    tell application "Finder"
      set appname to name of application file id "$1"
      return 1
    end tell
  on error err_msg number err_num
    return 0
  end try
end run
EOF`

retcode=`osascript -e "$APPLESCRIPT"`
exit $retcode

脚本需要一个应用程序标识符(例如 com.apple.preview)。执行脚本后,retcode 如果安装了应用程序,则包含 1,如果未安装应用程序,则包含 0。该脚本还返回retcode

例如:

$ ./appinst.sh com.apple.preview
$ echo $?
1
$

$ ./appinst.sh nonono
$ echo $?
0
$

【讨论】:

  • 很酷的东西。这是一个更简洁的变体:一个 bash 函数,它接受一个包 ID,如果找到则返回应用程序的路径,否则返回一个空字符串:getAppPathByBundleId() { osascript -e 'try' -e 'tell application "Finder" to return POSIX path of (path to application file id "'"$1"'") as text' -e 'end try'; }。另请参阅我的答案,以按应用名称进行测试并查找应用的捆绑 ID。 (请注意,绕过 Finder 上下文并简单地使用例如 application id "com.apple.reminders",这很诱人,因为我刚刚学会了艰难的方法,它可以工作,但隐式启动指定的应用程序。)
【解决方案3】:

您可以为此使用system_profiler 命令。试试这样的:

system_profiler SPApplicationsDataType | grep AppName

【讨论】:

  • 这很值得知道,但在只对特定应用程序感兴趣的脚本中使用可能太慢了。
【解决方案4】:

在大多数情况下,所有第三方应用程序都安装在 Applications 文件夹中。最简单的方法就是通过 grep。

ls /Applications/ | grep -i APP_NAME

只需将 APP_NAME 替换为您要查找的任何内容。 “-i”使 grep 不区分大小写,因此除非安装了一些重大拼写错误,否则它将列出文件。否则它什么也不会返回。

【讨论】:

  • 正如您所暗示的,应用程序可以位于其他位置,尤其是~/Applications,但甚至可以位于其他非标准位置。因此,@Bavarious 的解决方案更可取。
  • 但是例如,如果我安装了一个不在应用程序文件夹中的 Cmake,在这种情况下,我如何检查是否安装了 cmake,此外,我如何正确删除 cmake。
【解决方案5】:

您可以使用 AppleScript 来询问应用程序的“ID”。 (但请参阅下面的更新以获得更可靠的方法!)

这是一个可用于 Bash 脚本以检查“QuickTime Player 7”是否可用的示例:

if osascript -e 'id of application "QuickTime Player 7"' >/dev/null 2>&1; then
    echo "Yes, QT 7 is available"
else
    echo "No, QT 7 not found"
fi

应用名称不区分大小写,所以“quicktime player 7”也可以。

如果您想在脚本中为应用程序名称使用 Bash 变量,请注意 AppleScript 需要在应用程序名称两边加上双引号。所以你需要写这样的东西,转义双引号:

app='QuickTime Player 7'
if osascript -e "id of application \"$app\"" >/dev/null 2>&1; then
   #...
fi

更新:

但是,正如我在使用的这个特定示例中发现的那样,应用程序名称可能会更改!在另一台机器上,同一个 QT 7 应用程序被命名为“QuickTime 7 Pro”而不是“QuickTime Player 7”。

因此,更可靠的解决方案是了解应用的 ID,该 ID 在不同的安装中应该保持不变。然后您可以检查该 ID 是否存在。

if osascript -e 'exists application id "com.apple.quicktimeplayer"' >/dev/null 2>&1; then
    ((debug)) && echo "OK: Quicktime 7 found" >&2
else
    echo "ERROR: Cannot find Quicktime 7" >&2
fi

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-05-12
    • 2011-07-06
    • 1970-01-01
    • 2020-12-14
    • 2020-09-09
    • 2013-03-24
    • 1970-01-01
    • 2016-04-26
    相关资源
    最近更新 更多