Search and replace over multiple files is difficult in my editor. There are plenty of tricks that can be done with find
, xargs
and sed
KISS principle:
vim
:args `ls`
:argdo %s#SEARCH#REPLACE#gec |update
First character afer %s is used as separator
you can try this tool for find and replace in intercative mode inner a shell
https://sourceforge.net/projects/isartool/
No X server is required, and if you want it's recursive in directory using the option -r.
Ciao
From jhvaras answer, I've made this bash command to quickly search and replace (to add to .bashrc
):
replace () {
if [ $# -lt 2 ]
then
echo "Recursive, interactive text replacement"
echo "Usage: replace text replacement"
return
fi
vim -u NONE -c ":execute ':argdo %s/$1/$2/gc | update' | :q" $(ag $1 -l)
}
It's used as follows:
~$ replace some_text some_new_text
It uses ag
to search in advance, as it's probably faster than letting vim
do the work, but you can probably substitute anything else you like. It also calls vim
with no plugins for maximum speed, and after it has finished all substitutions it automatically quits and goes back to the shell.
Here is an enhancement of @jhvaras's answer if you find that you frequently want to do this, or if you only want to search files under version control.
function SvnProjectSubstitute(replacement)
execute "args `grep -sl '" . @/ . "' $(svn --recursive list)`; echo -n ''"
argdo execute "substitute//" . a:replacement . "/gc"
endfunction
command -nargs=1 -complete=file Gsubstitute call SvnProjectSubstitute(<f-args>)
Notes:
Gsubstitute
is for "global substitute". You can call the command whatever you want but I like this because :Gs
seems to fit stylistically into Vim.-s
passed to grep
are to cover up an errors that grep
encounters. grep
gives a non-zero return code even if it does find good results.Example use:
/OldClassName
:Gs NewClassName
One reason I like using the previous search pattern is it allows you to quickly give a class an entirely different name by placing your cursor on the class, doing a * or a #, and then your :Gs
command, which saves you from having to type out the whole search string.
Just use Vim.
Start by using find to make a list of all files which need changing like so.
vim `find . -name '*.c' -exec grep junk {} \;`
That starts vim with all the .c
files containing the string junk
. Now, in vim make your change to the first file:
:%s/junk/rubbish/g
And then type :wEnter:nEnter for the next file.
Now you need to repeat the editing process. If it is only one substitute command and just a few files, then type :UpEnter to repeat the substitute command.
But if there are a lot, you should use map
to create a couple of kestroke macros. The first macro would do the substitute command(s) and the second macro would do the w
and n
commands to save changes and get the next file.
I have used this (and older variants with vi) for the past 30 years. In particular, when you encode the two parts of this as two keystroke macros, you can run it very fast because it is easy to hold down the control key, and type a couple of letters, for instance R Y, over and over again. It is faster than the time it takes to write a fully automated script and since this is simple to reproduce, you can do it on any machine that you happen to be working on.
I would add these modifications to Dillon's answer:
The -le
option should be added to the grep
command.
vim `find . -name '*.c' -exec grep -le '\<junk\>' {} \;`
Then you are in Vim, but you don't have the opportunity to choose what to replace, add c
option at the end for interactive replacements and bufdo
at the beginning for walking through every file:
:bufdo %s/junk/rubbish/gce
Later you save all your work:
:bufdo wq!