【问题标题】:Homebrew: how to list the N last installed packages?Homebrew:如何列出最后安装的 N 个软件包?
【发布时间】:2021-06-05 01:31:13
【问题描述】:

简单地说:我想列出我用 Homebrew 安装的最后 N 个软件包。

什么是最好的(也可能是最快的)实现这一点的方法?

请注意,我的 Ruby 语言并不流利,所以任何关于“破解 Homebrew 代码以做你想做的事”的建议都会让我感到紧张......

到目前为止我尝试了什么

  1. 阅读手册页、文档、Homebrew 网站、StackOverflow,用谷歌搜索各种不同的问题等。到目前为止还没有运气。
  2. brew info [formula|cask] 实际上会告知配方/酒桶被倾倒的日期(我认为这意味着在 Homebrewosphere 之外“安装”)。所以这个值必须写在某个地方——一个数据库?日志?
  3. 也许有一个选项可以通过JSON API 提取浇注日期信息?但事实是,使用 Homebrew 3.1.9-121-g654c78c,我无法在 JSON 输出中获得任何 poured-date 或类似元素......我得到的唯一日期与 git 相关(可能是因为它们'对于 Homebrew 的内部工作更有用)。从理论上讲,这将能够告诉我我安装的公式的“最新”版本是什么,但 不是 我安装它们的 顺序 - 在其他话说,我昨天可以装一岁的版本,我不需要知道它是一岁,我只想知道我昨天已经安装了!

到目前为止我学到了什么

虽然我不知道如何检索该信息,但我确定它在那里,因为brew info ...给出正确 一天倒了一个特定的配方。因此,一种可能的解决方案是从brew info 捕获所有信息,然后对其执行grep;因此,像brew info | grep Poured 这样的东西应该给我我想要的东西。不用说,这需要 eternities 才能运行(事实上,我从未设法完成它——几分钟后我就放弃了)。

当然,我发现一个brew info --installed 选项——但目前,它只适用于 JSON 输出。而且由于 JSON 输出不会告诉浇注日期,这没有用。

一种可能性是通过以下方式进行:

  • brew info --installed --json=v1 | jq "map(.name)" > inst.json提取所有已安装的包名
  • 解析结果,使其成为单行,例如cat inst.json | tr -d '\n\r\[\]\"\,'
  • 现在运行brew info --formula(将所有内容视为公式以避免警告),将结果通过管道传输到另一个文件中(例如all-installed.txt
  • 浏览该文件,提取包含公式名称和日期的行,并使用cat all-installed.txt | sed -E 's/([[:alnum:]]+):? stable.*\n(.*\n){3,7}^ Poured from bottle on (.*)$/\1 -- \3\\n/g' | sort | tail -40 之类的格式对其进行格式化——我们的想法是只包含日期和公式名称的行,以便轻松获取排序 [注意:我知道显示的正则表达式不起作用,这只是我放弃这种方法之前失败尝试的一部分]

凌乱。处理所有事情也需要很多时间。如果您准备盯着空白屏幕等待几分钟,可以将所有内容放在一行中并避免中间文件。

快速而肮脏的方法

我试图寻找 a) 安装日志; b) 某种数据库,brew 将存储我试图提取的信息(并且 brew info 可以访问)。我发现的大多数“日志”实际上都与修补单个软件包有关(因此,如果出现问题,您可能可以通过电子邮件向维护者发送电子邮件)。但是,我注意到,每个包在/usr/local/Cellar/ 中都有一个INSTALL_RECEIPT.json似乎输出为brew info --json=v1 package-name。不管这个文件的目的是什么,它都有一些宝贵的信息:它是在安装这个包的日期创建的!

这对我来说相当幸运,因为现在我可以简单地stat 这个文件并获得它的创建时间戳。因为公式目录的格式非常好并且易​​于解析,所以我可以做一些非常简单的事情,只需使用stat 和一些格式化的东西,我花了很长时间才弄清楚(主要是因为 stat 在 BSD-inspired Unixes 下有与受 SysV 启发的 Linux 流行的选项不同)。

例如,要获取最近安装的 40 个公式:

stat -t '%Y%m%d%H%M' -f "%Sc %N %@" /usr/local/Cellar/*/*/INSTALL_RECEIPT.json | sort | tail -40

这运行得相当快,而且我确实设法得到了另一个项目想要/需要的东西(列出我必须安装的最后几个公式,以便运行我试图使用的某个软件包在 macOS 下编译并记录需要的内容),但我一直想知道这是否是“最佳”方法。当然,它已经足够快了——使用标准工具遍历文件系统树比期望 Ruby 完成其慢节奏的工作要快得多——但是我怎么知道我有“正确”的信息呢? 所有包都有INSTALL_RECEIPT.json吗?如果 Homebrew 核心开发人员考虑彻底改变整个目录结构怎么办?或者停止写入INSTALL_RECEIPT.json 文件,因为他们使用“其他地方”(在哪里?)的数据库,这变得多余了?换句话说——我如何才能以一种面向未来的方式找出我想要的东西,只依赖brew 命令已经提供的任何信息?

无论如何,为了争论,我非常欢迎看到一些关于如何正确执行此操作的建议正确 - 并且没有像我对 stat 所做的那样“作弊”(例如根本不通过brew 命令,而是依赖文件系统本身)。

或者这样的功能可能不存在,我应该在 Homebrew 的 GitHub 问题上提出功能请求? (毕竟,Debian/Ubuntu Linux 用户一种方法来get that information 使用apt 的一些参数和一些解析......我们'值得'相同,甚至更好!? ???)

【问题讨论】:

    标签: macos homebrew jq


    【解决方案1】:

    “brew list”命令有一个 -t 选项:

    按修改时间对配方和/或木桶进行排序,首先列出最近修改的。

    因此要获得最近的 40 个,您可以这样写:

    brew list -1t 2> /dev/null | head -n 40
    

    还有一个 -l 选项,显示使用的时间戳。

    运行brew list -t -v 显示幕后发生的事情;在我的机器上,输出开始:

    ==> Formulae
    ls -t /usr/local/Cellar
    

    所以很明显brew list(目前)依赖于“地窖”。

    如果 brew list 太慢了,我认为将 HOMEBREW_PREFIX(如 brew --prefix 所揭示)与 CellarCellar/*/*/INSTALL_RECEIPT.json 结合使用是合理的

    .时间

    每个 INSTALL_RECEIPT.json 中的 JSON 对象都有一个 .time 键,这可能比文件或目录时间戳更可靠,因此您可能想考虑类似以下 bash 脚本:

    CELLAR=$(brew --prefix)/Cellar
    jq -nr --arg cellar "$CELLAR" '
      [inputs | {time, file: (input_filename|sub($cellar;"") | sub("/INSTALL_RECEIPT.json";""))}]
      | sort_by(.time)[-40:][]
      | .file
    ' $CELLAR/*/*/INSTALL_RECEIPT.json
    

    【讨论】:

    • 谢谢,这正是我想要的! :-) 不知何故,我在执行brew help list 时错过了-t 标志。但它肯定在那里!它几乎可以满足我的需要,and 对于我的目的来说已经足够快了。您的第二个解决方案有点复杂,但它具有解释.time 参数在INSTALL_RECEIPT.json 中的含义的优点。我查过了,确实是“正确”的时间!
    • 顺便提一下,brew info --json installed 引出的 JSON 应该是有时间的,所以提出增强是有意义的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-02-08
    • 2020-04-12
    • 2013-06-15
    • 1970-01-01
    • 1970-01-01
    • 2013-07-30
    • 2013-04-04
    相关资源
    最近更新 更多