Homebrew:如何列出最近安装的 N 个软件包?

Gwy*_*lyn 3 macos homebrew jq

简而言之:我想列出我用 Homebrew 安装的最后 N 个软件包。

\n

实现这一目标的最佳(可能也是最快)方法是什么?

\n

请注意,我对 Ruby 不太熟悉,因此任何“破解 Homebrew 代码以执行您想要的操作”的建议都会让我感到紧张......

\n

到目前为止我尝试过的

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

到目前为止我学到了什么

\n

虽然我不知道如何检索该信息,但我确信它就那里,因为brew info ... 给出正确的日期浇注特定的公式。因此,一种可能的解决方案是捕获所有信息brew info,然后grep对其进行处理;因此,类似的东西brew info | grep Poured应该给我我想要的东西。不用说,这需要永恒的时间才能运行(事实上,我从未成功完成它 \xe2\x80\x94 我在几分钟后放弃了)。

\n

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

\n

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

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

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

\n

快速而肮脏的方法

\n

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

\n

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

\n

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

\n
stat -t \'%Y%m%d%H%M\' -f "%Sc %N %@" /usr/local/Cellar/*/*/INSTALL_RECEIPT.json | sort | tail -40\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n

无论如何,为了论证,我非常欢迎看到一些关于如何正确执行此操作的建议\xe2\x80\x94 并且不会像我那样进行“作弊” stat(例如,不通过brew命令完全依赖于文件系统本身)。

\n

或者也许这样的功能不存在,我应该在 Homebrew 的 GitHub 问题上提出功能请求?(毕竟,Debian/Ubuntu Linux 用户可以使用一些参数和一些解析来获取该信息......我们“值得”相同,甚至更好!apt

\n

pea*_*eak 8

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

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

因此,要获取最近的 40 个,您可以编写:

brew list -1t 2> /dev/null | head -n 40
Run Code Online (Sandbox Code Playgroud)

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

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

==> Formulae
ls -t /usr/local/Cellar
Run Code Online (Sandbox Code Playgroud)

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

如果brew list对您来说太慢,我相信将 HOMEBREW_PREFIX (如 所示)与 或 结合使用是合理brew --prefixCellarCellar/*/*/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
Run Code Online (Sandbox Code Playgroud)

  • 顺便说一句,由“brew info --jsoninstalled”引出的 JSON 大概应该有时间,因此提出增强功能是有意义的。 (2认同)