11 个版本

0.1.10 2024年6月13日
0.1.9 2022年9月17日
0.1.8 2022年4月22日
0.1.7 2022年3月17日
0.1.3 2021年5月27日

#146 in 文件系统

EUPL-1.1

63KB
1.5K SLoC

钼替换器

基于行的递归搜索和替换命令行应用程序。

安装

直接通过 cargo 安装

  • 安装 rust,这应该也会安装 cargo
  • 运行 cargo install molybdenum
  • 验证成功:mo -h 应该打印其帮助和版本

从源代码

  • 安装 rust,这应该也会安装 cargo
  • 克隆仓库:git clone https://github.com/gfannes/molybdenum
  • 构建和安装应用程序:cargo install --path molybdenum
  • 验证成功:mo -h 应该打印其帮助和版本

基本用法

以下命令演示了如何使用 mo 完成不同的任务

  • 创建文件名列表,仅对路径名本身进行过滤
    • mo:当未指定搜索模式时,仅列出文件名
    • mo -l:明确要求输出文件名
    • mo -C FOLDER:将 FOLDER 作为搜索的根目录
    • mo -e hpp -e cpp:仅考虑具有 hppcpp 扩展名的文件
    • mo -f PART:保留与 PART 匹配的文件名
    • mo -F PART:保留不与 PART 匹配的文件名
    • mo -0:使用0x00来分隔文件名。当与xargs结合使用时,这非常有用。
    • mo -u -U -a:同时考虑隐藏文件、文件夹和二进制文件。
  • 搜索指定的正则表达式模式
    • mo PATTERN:递归地搜索文件中的PATTERN
    • mo -p PATTERN:递归地搜索文件中的PATTERN
    • mo -w PATTERN:递归地搜索文件中的PATTERN,在PATTERN周围添加单词边界约束
    • mo -s PATTERN:搜索PATTERN,区分大小写
    • mo -B 10 -A 10 PATTERN:在每个匹配项前后输出10行额外的上下文
  • 将匹配项替换为指定的字符串
    • mo needle -w -r naald -n模拟将单词needle替换为荷兰语单词naald
    • mo needle -w -r naald真正将单词needle替换为荷兰语单词naald
  • xargs结合使用
    • mo -l -C FOLDER -0 | xargs -0 -r mo -i PATTERN:注意-i选项,以确保mo在文件中进行搜索而不是在标准输入中进行。此外,应设置xargs -r选项,以确保在没有文件路径生成的情况下不会运行任何内容。

此外,mo会检测输入是否来自控制台或重定向,并相应地执行,同样适用于其输出:mo还可以用于在管道流中进行报告或替换。

交互式文件选择

以下bash函数允许您根据fzf的模糊搜索功能打开文件(o)更改文件夹(c)。您可以传递任何mo接受的参数,使它们成为方便的交互式工具。它们依赖于bat提供预览,以及nvr在新或已运行的实例中打开所选文件,以及zoxide注册和跟踪您最受欢迎的文件夹。

# Open file using `bat` as preview
o() {
    mo -l $* | fzf --multi --preview 'bat --style=numbers --color=always --line-range :500 {}' --preview-window 'right:60%' | xargs -I % nvr --remote-tab %
}

# Open file using `mo` as preview
s() {
    export all_args="$*"
    mo -l $* | fzf --multi --preview 'mo -c -i ${all_args} -C {}' --preview-window 'right:60%' | xargs -I % nvr --remote-tab %
}

# Change to dir using `z`
c() {
    z `mo -L $* | fzf`
}

还有其他工具吗?

可以在没有问题的情况下找到强大的搜索工具,例如,grepackagripgrepbroot

在文件夹中递归替换工具比较难找,尽管一些工具存在:[fart-it](https://github.com/lionello/fart-it)。通常,人们会结合使用搜索、[xargs](https://www.thegeekstuff.com/2013/12/xargs-examples/) 和替换工具如 [sed](https://www.grymoire.com/Unix/Sed.html) 或 [rpl](http://rpl.sourceforge.net/)。

我在尝试替换之前,经常使用代码搜索来调查大型源代码库。即使有10万个文件,搜索也是快速且相对容易的。递归地替换文本则要危险得多,尤其是如果需要组合多个不常用的工具;如果不是每天使用,就很难记住 search-xargs-replace 组合。更不用说,用于过滤文件集并执行试运行的 search 工具,并不一定是使用与 replace 工具相同的搜索查询。毕竟,这些是不同的工具。如果能有一个工具可以用于日常的搜索和替换那就更好了。这正是 The Molybdenum Replacer 所要实现的目标。

此外,我发现使用 agrg 来过滤文件路径和搜索剩余文件中的内容比较困难;在我看来,agrg-g 选项很令人困惑。因此,我期望 ag -g /auro/ -w test 会搜索所有路径中包含 /auro/ 的文件中的单词 test,但这并不是实际情况。它使用 /auro/test 来过滤文件名(或看起来像文件名的东西)。

当然,真正的理由是我有一些空闲时间,正在寻找一个不错的项目/借口来学习 [Rust](http://www.rust-lang.net.cn/).

已实现的功能

以下功能已在当前版本中实现并可用

  • 在嵌套文件夹结构中进行递归 搜索,基于行
    • 足够快,可以实际使用。我的感觉是它的性能介于 [ag](https://github.com/ggreer/the_silver_searcher) 和 [ripgrep](https://github.com/BurntSushi/ripgrep) 之间。
    • 在控制台输出时,输出足够清晰,以便人类可以理解
  • 在嵌套文件夹结构中进行递归 替换
  • 从输入流进行 搜索替换
    • 当输出被重定向时,输出所有输入
  • 支持非UTF8文件名和内容
  • 对二进制文件的粗略检测
  • 灵活指定搜索根和模式
    • 允许在模式上方指定搜索根
    • 允许在搜索根和模式后使用破折号选项
  • 改进的xargs集成
    • 支持当指定为根时搜索单个文件
    • 支持覆盖自动检测的stdin重定向/tty控制台检测
  • 支持多个搜索根
  • 支持针对 .gitignore 文件进行过滤
  • 支持使用 -L 选项列出文件夹名称

未来功能

以下功能可能会迟早添加

  • 不接受带前导破折号的 PATTERN 和 PATH
  • 当某些文件夹权限不足时,不会失败
  • 默认情况下不替换:反转 -n 的解释(并使用不同的名称)
  • 支持不带缩写表示法的参数
  • 支持显示单个参数的内容,最好使用 -c
  • 支持文件类型集合
  • 允许合并无参数选项: mo -ws test
  • 允许显式设置输入分隔符。现在,这是硬编码的 0x0a
  • 性能提升
    • mo 目前是单线程的。为了达到 ripgrep 类似的性能,可能需要所有 CPU。
    • 当使用 -l 仅输出文件名时,mo 可在找到第一个匹配项后停止搜索。
  • 检测到重定向输出时,按行报告单个匹配
    • 允许使用 wc 来计数匹配
  • 支持省略匹配的行号
  • 支持反转每行的匹配
  • 使用更好的名称,我只是挑选了一个还可用的事物。
    • 没有人能记住 molybdenum,而且很难输入。 mo 更好,但在互联网上搜索困难。
  • 更好的二进制文件检测
  • 在写入替换文件失败时回滚
  • 测试改进
    • 更多和更好的单元测试
    • 对所有常见用例进行验收测试
    • 性能测试和相关的报告
  • github 上发布二进制版本
  • 为使用浅色主题的用户改进颜色方案
  • 为版本 v0.1.6 之前的版本添加更改日志。

性能

计算文件夹中的所有文件

Scenario: count all files
  Running `mo -l -u -U -a | wc`
    Elapsed time: 0:00.29
    Output:  184675  187146 16959297

  Running `rg --files -uu -a | wc`
    Elapsed time: 0:00.15
    Output:  184675  187146 16589947

  Running `ag -l -uu -a | wc`
    Elapsed time: 0:00.66
    Output:  184675  187146 16589947

在 C++ 源代码中搜索单词

Scenario: search for word `test` in .cpp files in subfolder `core` where path contains /auro/
  Running `mo -C core -e cpp -f /auro/ -w -p test -l | wc`
    Elapsed time: 0:00.03
    Output:     165     165    9008

  Running `rg -t cpp --files core | rg /auro/ | rg '.cpp$' | tr '\n' '\0' | xargs -0 rg -i -w test -l | wc`
    Elapsed time: 0:00.01
    Output:     165     165    9008

  Running `ag --cpp -l . core | ag /auro/ | ag '.cpp$' | tr '\n' '\0' | xargs -0 ag -w test -l | wc`
    Elapsed time: 0:00.05
    Output:     165     165    9008

我不知道如何使用 agrg 在单个命令中完成此场景,而不依赖于 xargstr

更改日志

v0.1.6

  • 当 stdout 不是 TTY 时,使用更紧凑且更有用的输出格式
  • .out 扩展名添加到二进制文件列表中

v0.1.7

  • -s 设置时,使用 -f-F 进行文件名模式匹配时,现在是区分大小写的。
  • 添加了原始方法来仅通过 -m 输出匹配。这应该用正则表达式子匹配支持替换。

v0.1.8

  • 支持处理捕获组。当指定 -P % 时,通过 -r 指定的替换字符串将替换所有 %%[0-9] 的出现。
  • 支持紧凑输出。
  • 重新设计彩色输出:未指定时,检查输出流。如果是 TTY,则不产生彩色输出。

v0.1.9

  • 当指定多个搜索模式时,实际上使用的是最后一个。这允许更好地与脚本集成,其中默认模式被指定,可能稍后会更新。

v0.1.10

  • 在遍历权限不足的文件夹时,这些文件夹会被跳过,处理继续。
  • 添加了对使用 $EDITOR 命令行选项打开文件的兼容性支持。最佳与 -l 选项配合使用。
  • 移除了 -R 选项

依赖

~4–15MB
~136K SLoC