How can I search and replace recursively in a directory in Vim?
recursion, search, vim
Solution
Even though I'm a Vim user, I generally use `find` and `sed` for this sort of thing. The regex syntax for `sed` is similar to Vim's (they're both descendants of `ed`), though not identical. With GNU sed you can also use `-i` for in-place edits (normally `sed` emits the modified version to stdout).
For example:
find project -name '*.rb' -type f -exec sed -i -e 's/regex/replacement/g' -- {} +
Piece by piece:
- `project` = search in "project" tree
- `-name '*.rb'` = for things whose names match '*.rb'
- `-type f` = and are regular files (not directories, pipes, symlinks, etc.)
- `-exec sed` = run `sed` with these arguments:
- `-i` = with in-place edits
- `-e 's/regex/replacement/g'` = execute a "substitute" command (which is almost identical to Vim's `:s`, but note lack of `%` -- it's the default in `sed`)
- `--` = end of flags, filenames start here
- `{}` = this tells `find` that the filenames it found should be placed on sed's command-line here
- `+` = this tells `find` that the `-exec` action is finished, and we want to group the arguments into as few `sed` invocations as possible (generally more efficient than running it once per filename). To run it once per filename you can use `\;` instead of `+`.
This is the general solution with GNU `sed` and `find`. This can be shortened a bit in special cases. For example, if you know that your name pattern will not match any directories you can leave out `-type f`. If you know that none of your files start with a `-` you can leave out `--`. Here's an answer I posted to another question with more details on passing filenames found with `find` to other commands.
Problem
I found out about Vim's substitute command... ``` :%s/replaceme/replacement/gi ``` And vimgrep... ``` :vimgrep /findme/gj project/**/*.rb ``` Is there a way to combine them in order to do a replacement across all the files under a directory?