2 unstable releases
0.1.0 | Jan 6, 2022 |
---|---|
0.0.1 | Dec 29, 2021 |
#2806 in Command line utilities
46KB
1K
SLoC
fnr – find and replace
Like find ... | xargs sed ...
, but with a memorable interface.
Recursively find and replace patterns in files and directories.
fnr [OPTIONS] FIND REPLACE [PATH...]
About
fnr
is intended to be more intuitive to use than sed
, but is not a
drop in replacement. Instead, it's focused on making bulk changes in a
directory, and is more comparable with your IDE or editor's find and
replace tool.
fnr is alpha quality. Don't use --write
in situations you
wouldn't be able to revert.
Examples
Replace "old_function"
with "new_function"
in current directory.
fnr old_function new_function
Choose files and directories to consider.
fnr 'EDITOR=vim' 'EDITOR=emacs' ~/.zshrc ~/.config/
We can use --literal
so the pattern isn't treated as a regular expression.
fnr --literal 'i += 1' 'i++'
Replace using capturing groups.
fnr 'const (\w+) = \d+;' 'const $1 = 42;'
Use -W --write
to write changes back to files.
fnr --write 'Linus Torvalds' 'Linux Torvalds'
Use -I --include
to only modify files or directories matching a pattern.
fnr --include 'Test.*\.kt' 'mockito' 'mockk'
Similarly, use -E --exclude
to ignore certain files.
fnr --exclude ChangeLog 2021 2022
Files and directories to consider can also be given over standard input.
find /tmp/ -name "*.csv" -print | fnr "," "\t"
Use -p --prompt
to individually accept or reject each replacement.
fnr --prompt --literal 'i++' '++i'
--- ./README.md: 2 matching lines
- 18: $ fnr --literal 'i += 1' 'i++'
+ 18: $ fnr --literal 'i += 1' '++i'
Stage this replacement [y,n,q,a,e,d,?] ?
Installation
cargo install fnr
If you'd prefer to build from source instead:
$ git clone git@github.com/erik/fnr.git
$ cd fnr
$ cargo install --path .
Performance
Built on top of ripgrep's path traversal and pattern matching, so even though performance isn't an explicit goal, it's not going to be the bottleneck.
In fact, without writing changes back to files, it's imperceptibly slower than ripgrep itself.
Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
---|---|---|---|---|
rg "EINVAL" ./linux |
510.4 ± 25.8 | 467.6 | 555.0 | 1.00 |
fnr "EINVAL" "ERR_INVALID" ./linux |
620.4 ± 22.1 | 573.7 | 649.7 | 1.22 ± 0.08 |
fnr --write "EINVAL" "ERR_INVALID" ./linux |
3629.0 ± 76.2 | 3538.0 | 3802.3 | 7.11 ± 0.39 |
ag "EINVAL" ./linux |
2560.0 ± 43.6 | 2518.4 | 2668.1 | 5.02 ± 0.27 |
grep -irI "EINVAL" ./linux |
37215.8 ± 7444.7 | 31316.1 | 49096.6 | 72.92 ± 15.04 |
Similar Tools
If fnr
doesn't quite fit what you're looking for, also consider:
- facebookincubator/fastmod - quite similar to
fnr
. - google/rerast - operates on Rust AST
- coccinelle - more advanced edits to C code
- ... many more
Dependencies
~13–24MB
~412K SLoC