How can I search and replace recursively in a directory in Vim?

前端 未结 7 695
抹茶落季
抹茶落季 2021-01-30 02:44

I found out about Vim\'s substitute command...

:%s/replaceme/replacement/gi

And vimgrep...

:vimgrep  /findme/gj  project/**/*.r         


        
7条回答
  •  孤城傲影
    2021-01-30 02:55

    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.

提交回复
热议问题