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 文件系统
63KB
1.5K SLoC
钼替换器
基于行的递归搜索和替换命令行应用程序。
安装
直接通过 cargo 安装
从源代码
- 安装 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
:仅考虑具有hpp
和cpp
扩展名的文件mo -f PART
:保留与 PART 匹配的文件名mo -F PART
:保留不与 PART 匹配的文件名mo -0
:使用0x00
来分隔文件名。当与xargs
结合使用时,这非常有用。mo -u -U -a
:同时考虑隐藏文件、文件夹和二进制文件。
- 搜索指定的正则表达式模式
mo PATTERN
:递归地搜索文件中的PATTERNmo -p PATTERN
:递归地搜索文件中的PATTERNmo -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`
}
还有其他工具吗?
可以在没有问题的情况下找到强大的搜索工具,例如,grep、ack、ag、ripgrep或broot。
在文件夹中递归替换工具比较难找,尽管一些工具存在:[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 所要实现的目标。
此外,我发现使用 ag
和 rg
来过滤文件路径和搜索剩余文件中的内容比较困难;在我看来,ag
和 rg
的 -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
我不知道如何使用 ag
和 rg
在单个命令中完成此场景,而不依赖于 xargs
和 tr
。
更改日志
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