我如何从Bash Mac中排除程序包文件(目录)?

时间:2018-08-18 19:37:01

标签: bash macos find

如何从Bash find命令的搜索路径中排除Mac Package文件?

macOS包含一些实际上是unix目录的“文件”。这些被称为“包装”。 Mac应用程序文件是一个很好的例子,但还有其他例子。不幸的是,我没有找到任何排除软件包的查找开关。

这是一个不起作用的典型find命令。它将在.app文件中搜索:

find /Applications -type f -path ./*.app -prune -o  -print

在这种情况下,我希望它列出实际的.app文件,但不要在其中搜索。

我尝试了很多这种变化,但都没有奏效。

以下是一些其他确实是软件包的典型文件扩展名:
.app .pkg .scptd

3 个答案:

答案 0 :(得分:1)

插入一个正则表达式条件,该条件对于包目录中的所有内容返回false。不幸的是,这确实意味着必须列出要排除其内容的软件包目录的文件扩展名。我已经在我的正则表达式字符串中列出了很多:

find -E /Applications ! -iregex '.*\.(app(download)?|scptd|pkg|bundle|qlgenerator|c?action|dictionary|cannedSearch|photoslibrary)/.+'

答案 1 :(得分:0)

尝试一下。我从另一个答案(来自用户anonymous-coward)获得了捆绑测试。将其放入一个小脚本中,并命名为“ bundle”,如下所示:

#!/bin/bash

content_tree=$(mdls -name kMDItemContentTypeTree "$@" | grep -E '\"com.apple.bundle\"')

[[ ! -z "$content_tree" ]] && exit 0 || exit 1

(随时改进我的bash。)如果自变量是束的路径,则束返回0(成功),否则返回1。它生成一些特定于Mac的元数据,并查找包特征。如果您想更具体地避免使用包而不是其他种类的捆绑包,则可以查找“ com.apple.package”。您的bundle脚本可以选择所需的任何内容。在某些文件上运行mdls -name kMDItemContentTypeTree,看看会出现什么,这将告诉您将什么正则表达式传递给grep。您可以对文件扩展名等进行其他测试。然后像这样形成您的find命令:

find /Applications \( -exec bundle {} \; -print -prune \) -or -print

我刚刚使用Applications是因为它是一个示例,您可以在其中找到许多捆绑包和包装。如果外壳程序结果不为0,-exec标签将返回false(因为0始终表示“成功”作为外壳程序结果)。因此,-or左侧的表达式表示如果某事物是捆绑包,我们将打印其完整路径,而-prune则表示我们不会继续进入目录。 -print右边看似多余的-or是因为如果您使用-exec或其他一些运算符,find将禁止所有打印,因此,如果出现以下情况,则需要打印路径它是一个包(或包或您的脚本检测到的任何东西),如果没有,则还会打印路径。注意:在测试结束后\;+之前使用-print而不是-prune是关键。否则,find会将大量文件分组以传递给bundle,并且您需要为每个文件获得一个答案。您可以在-print的任一侧或两侧将-exec运算符替换为-or,以防以某种方式处理文件而不仅仅是查找文件。原来,这是您要不同处理的任何两类文件的示例。希望这是有用的。这是一个有趣的练习,实际上在思考find及其应用方面非常有用。

答案 2 :(得分:0)

要与 @cycollins 很好的答案相吻合,以下是辅助脚本的另一种形式(以及否定的味道),它更加简洁:

将此保存为 is_bundle 在您的$PATH中的某个地方:

#!/usr/bin/env bash
mdls -name kMDItemContentTypeTree "$1" | egrep -q '\"com.apple.(bundle|package)\"'

,并将其另存为 is_not_bundle

#!/usr/bin/env bash
mdls -name kMDItemContentTypeTree "$1" | egrep -q '\"com.apple.(bundle|package)\"'
[ $? -eq 0 ] && exit 1 || exit 0

以下是一些用法示例:

  • 仅查找包含<pattern>(完全省略捆绑软件)的目录

    find -s . -type d -iname "*pattern*" -exec is_not_bundle {} \; -print

  • 查找包含<pattern>的任何东西-不要分成束:

    find -s . -iname "*pattern*" \( -exec is_bundle {} \; -print -prune -or -print \)

  • 查找目录捆绑包(但不要进入捆绑包)

    find -s . -type d -mindepth 1 \( -exec is_bundle {} \; -print -prune -or -print \)

  • 仅查找 个捆绑包

    find -s . -type d -exec is_bundle {} \; -print -prune

  • 查找与<pattern>匹配的捆绑商品

    find -s . -iname "*pattern*" -exec is_bundle {} \; -print -prune