【问题标题】:How Do I Exclude Package Files (Directories) from Bash Mac find?如何从 Bash Mac 查找中排除包文件(目录)?
【发布时间】:2019-01-25 11:25:16
【问题描述】:

如何从 Bash 查找命令的搜索路径中排除 Mac 包文件?

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

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

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

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

我已经尝试了很多变体,但都没有奏效。

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

【问题讨论】:

  • 那些试图帮助你的人投反对票的回答不会让你喜欢,也不会鼓励他们或其他人将来回答你。尤其是当由于您的示例过于简单而导致答案没有达到您想要的效果时。无论如何,当其他更相关的答案出现时,不太有用的答案将自动沉入底部 - 没有必要用大锤敲打他们的头。

标签: bash macos find


【解决方案1】:

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

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

【讨论】:

  • 谢谢,CJK,这似乎可以完成这项工作,但它不是我运行过的最快的工具。在我的快速 iMac-27 上花了大约 12 秒,这通常很快。
  • 是的,它必须考虑的文件扩展名越多,进程就越慢。如果您主要使用此工具来搜索您确信包含特定包类型的目录,则最好从该列表中删除不太常见的目录以加快搜索速度。
【解决方案2】:

试试这个。我从另一个答案(来自用户anonymous-coward)得到了捆绑测试。把它写成一个小脚本,叫它“bundle”,如下:

#!/bin/bash

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

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

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

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

我只使用了Applications,因为它是一个示例,您可以在其中找到很多捆绑包和包。如果 shell 结果不为 0,-exec 标记返回 false(因为 0 始终意味着作为 shell 结果的“成功”)。所以,-or 左边的表达式意味着如果某个东西是一个包,我们将打印它的完整路径,-prune 意味着我们不会进入目录。 -or右侧看似多余的-print是因为如果使用-exec或其他一些运算符,find会抑制所有默认打印,所以如果是bundle则需要显式打印路径(或包或您的脚本检测到的任何内容),如果不是,还打印路径。注意:在-print-prune 之前的测试结束时使用\; 而不是+ 是关键。否则find 会将大量文件分组以传递给bundle,您需要为每个文件获得一个答案。您可以在-or 的任一侧或两侧将-print 运算符替换为-exec,以防您想以某种方式处理文件,而不仅仅是搜索它们。事实证明,这是您想要以不同方式处理的任何两类文件的示例。希望这是有用的。这是一个有趣的练习,实际上在思考形成find 表达式方面非常有趣。

【讨论】:

    【解决方案3】:

    为了与 @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

    【讨论】:

      猜你喜欢
      • 2018-12-15
      • 2011-12-29
      • 2021-10-06
      • 2021-11-22
      • 2015-06-27
      • 1970-01-01
      • 1970-01-01
      • 2019-10-08
      • 2011-04-24
      相关资源
      最近更新 更多