Homebrew:如何列出最近安装的 N 个包?
Homebrew: how to list the N last installed packages?
简单地说:我想列出我用 Homebrew 安装的最后 N 个包。
完成此任务的最佳(可能最快)方法是什么?
请注意,我的 Ruby 不是很流利,所以对 'hack the Homebrew code to do what you want' 的任何建议都会让我感到紧张...
到目前为止我尝试了什么
- 阅读手册页、文档、Homebrew 网站、Whosebug,用谷歌搜索各种不同的问题等。到目前为止运气不好。
brew info [formula|cask]
实际上会告诉 formula/cask 被 倒出 的日期(我假设这意味着 'installed' 在 Homebrewosphere 之外)。所以这个值必须写在某个地方——数据库?日志?
- 也许有一个选项可以通过 JSON API 提取倒酒日期信息?但事实是,使用 Homebrew 3.1.9-121-g654c78c,我无法在 JSON 输出中获得任何
poured-date
或类似元素......我得到的唯一日期与 git
(大概是因为它们对 Homebrew 的内部工作更有用)。从理论上讲,这可以告诉我我安装的公式的 'newest' 版本是什么,但是 不是 order 我已经安装了它们——换句话说,我可以在昨天安装一个一年前的版本,我不需要知道它是一年前的,我只想知道我昨天安装了它!
到目前为止我学到了什么
虽然我不知道如何检索该信息,但我确定它在那里,因为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 (.*)$/ -- \n/g' | sort | tail -40
的格式对其进行格式化——我们的想法是只包含日期和公式名称的行,这样它可以很容易地排序[注意:我知道显示的正则表达式不起作用,这只是我放弃这种方法之前失败尝试的一部分]
凌乱。处理所有事情也需要很多时间。如果您准备盯着空白屏幕等待几分钟,您可以将所有内容放在一行中并避免使用中间文件。
快速而肮脏的方法
我试图寻找 a) 安装日志; b) 某种数据库,其中 brew
将存储我试图提取的信息(并且 brew info
可以访问)。我发现的大多数 'logs' 实际上都与修补单个软件包有关(这样如果出现问题,您大概可以给维护者发电子邮件)。然而,一个偶然的机会,我也注意到每个包裹在/usr/local/Cellar/
里面都有一个INSTALL_RECEIPT.json
,似乎 brew info --json=v1 package-name
的输出。无论此文件的用途是什么,它都有一点宝贵的信息:它是在安装此软件包的日期创建的!
这对我来说真是太幸运了,因为 现在 我可以简单地 stat
这个文件并获得它的创建时间戳。因为公式目录的格式非常好并且易于解析,所以我可以做一些非常简单的事情,只需使用 stat
和一些格式化的东西,这让我花了很长时间才弄清楚(主要是因为 BSD 下的 stat
受 SysV 启发的 Unix 有不同的选择 Linux).
例如获取最近安装的40个公式:
stat -t '%Y%m%d%H%M' -f "%Sc %N %@" /usr/local/Cellar/*/*/INSTALL_RECEIPT.json | sort | tail -40
这个 运行 相当快,我当然设法得到了我 wanted/needed 另一个项目的确切内容(列出我必须安装的最后几个公式 运行 我试图在 macOS 下编译并记录所需内容的某个软件包),但我一直想知道这是否是 'best' 方法。当然,它足够快 — 使用标准工具遍历文件系统树比期望 Ruby 执行其慢节奏工作要快得多 — 但我怎么知道我有 'correct' 信息? 所有 包都有 INSTALL_RECEIPT.json
吗?如果 Homebrew 核心开发人员想到完全改变整个目录结构怎么办?或者停止写入那个 INSTALL_RECEIPT.json
文件,因为他们使用数据库 'elsewhere'(在哪里?),这变得多余了?换句话说——我怎样才能以面向未来的方式找出我想要的东西,只依赖于 brew
命令已经提供的任何信息?
无论如何,为了争论,我非常欢迎看到一些关于如何正确的建议——而且没有'cheating',因为我使用 stat
完成(例如,根本不通过 brew
命令,而是依赖文件系统本身)。
或者这样的功能可能不存在,我应该对 Homebrew 的 GitHub 问题提出功能请求? (毕竟,Debian/Ubuntu Linux 用户 有办法 get that information 使用 apt
的一些参数和一些解析.. .我们'deserve'一样,甚至更好!)
“brew list”命令有一个 -t 选项:
Sort formulae and/or casks by time modified, listing most recently modified first.
因此要获得最近的 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
所揭示)与 Cellar
结合使用是合理的或 Cellar/*/*/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
简单地说:我想列出我用 Homebrew 安装的最后 N 个包。
完成此任务的最佳(可能最快)方法是什么?
请注意,我的 Ruby 不是很流利,所以对 'hack the Homebrew code to do what you want' 的任何建议都会让我感到紧张...
到目前为止我尝试了什么
- 阅读手册页、文档、Homebrew 网站、Whosebug,用谷歌搜索各种不同的问题等。到目前为止运气不好。
brew info [formula|cask]
实际上会告诉 formula/cask 被 倒出 的日期(我假设这意味着 'installed' 在 Homebrewosphere 之外)。所以这个值必须写在某个地方——数据库?日志?- 也许有一个选项可以通过 JSON API 提取倒酒日期信息?但事实是,使用 Homebrew 3.1.9-121-g654c78c,我无法在 JSON 输出中获得任何
poured-date
或类似元素......我得到的唯一日期与git
(大概是因为它们对 Homebrew 的内部工作更有用)。从理论上讲,这可以告诉我我安装的公式的 'newest' 版本是什么,但是 不是 order 我已经安装了它们——换句话说,我可以在昨天安装一个一年前的版本,我不需要知道它是一年前的,我只想知道我昨天安装了它!
到目前为止我学到了什么
虽然我不知道如何检索该信息,但我确定它在那里,因为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 (.*)$/ -- \n/g' | sort | tail -40
的格式对其进行格式化——我们的想法是只包含日期和公式名称的行,这样它可以很容易地排序[注意:我知道显示的正则表达式不起作用,这只是我放弃这种方法之前失败尝试的一部分]
凌乱。处理所有事情也需要很多时间。如果您准备盯着空白屏幕等待几分钟,您可以将所有内容放在一行中并避免使用中间文件。
快速而肮脏的方法
我试图寻找 a) 安装日志; b) 某种数据库,其中 brew
将存储我试图提取的信息(并且 brew info
可以访问)。我发现的大多数 'logs' 实际上都与修补单个软件包有关(这样如果出现问题,您大概可以给维护者发电子邮件)。然而,一个偶然的机会,我也注意到每个包裹在/usr/local/Cellar/
里面都有一个INSTALL_RECEIPT.json
,似乎 brew info --json=v1 package-name
的输出。无论此文件的用途是什么,它都有一点宝贵的信息:它是在安装此软件包的日期创建的!
这对我来说真是太幸运了,因为 现在 我可以简单地 stat
这个文件并获得它的创建时间戳。因为公式目录的格式非常好并且易于解析,所以我可以做一些非常简单的事情,只需使用 stat
和一些格式化的东西,这让我花了很长时间才弄清楚(主要是因为 BSD 下的 stat
受 SysV 启发的 Unix 有不同的选择 Linux).
例如获取最近安装的40个公式:
stat -t '%Y%m%d%H%M' -f "%Sc %N %@" /usr/local/Cellar/*/*/INSTALL_RECEIPT.json | sort | tail -40
这个 运行 相当快,我当然设法得到了我 wanted/needed 另一个项目的确切内容(列出我必须安装的最后几个公式 运行 我试图在 macOS 下编译并记录所需内容的某个软件包),但我一直想知道这是否是 'best' 方法。当然,它足够快 — 使用标准工具遍历文件系统树比期望 Ruby 执行其慢节奏工作要快得多 — 但我怎么知道我有 'correct' 信息? 所有 包都有 INSTALL_RECEIPT.json
吗?如果 Homebrew 核心开发人员想到完全改变整个目录结构怎么办?或者停止写入那个 INSTALL_RECEIPT.json
文件,因为他们使用数据库 'elsewhere'(在哪里?),这变得多余了?换句话说——我怎样才能以面向未来的方式找出我想要的东西,只依赖于 brew
命令已经提供的任何信息?
无论如何,为了争论,我非常欢迎看到一些关于如何正确的建议——而且没有'cheating',因为我使用 stat
完成(例如,根本不通过 brew
命令,而是依赖文件系统本身)。
或者这样的功能可能不存在,我应该对 Homebrew 的 GitHub 问题提出功能请求? (毕竟,Debian/Ubuntu Linux 用户 有办法 get that information 使用 apt
的一些参数和一些解析.. .我们'deserve'一样,甚至更好!)
“brew list”命令有一个 -t 选项:
Sort formulae and/or casks by time modified, listing most recently modified first.
因此要获得最近的 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
所揭示)与 Cellar
结合使用是合理的或 Cellar/*/*/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