How do I find and replace every occurrence of:
foo
with
bar
in every text file under the /my/test/dir/ directory tree (recursive find/replace).
BUT I want to be able to do it safely within an SVN checkout and not touch anything inside the .svn directories
Similar to this but now with the SVN restriction: Awk/Sed: How to do a recursive find/replace of a string?
Recursive Search To recursively search for a pattern, invoke grep with the -r option (or --recursive ). When this option is used grep will search through all files in the specified directory, skipping the symlinks that are encountered recursively.
Use the find command to recursively search the directory tree for each specified Path, seeking files that match a Boolean expression written using the terms given in the following text.
An easy way to do this is to use find | egrep string . If there are too many hits, then use the -type d flag for find. Run the command at the start of the directory tree you want to search, or you will have to supply the directory as an argument to find as well. Another way to do this is to use ls -laR | egrep ^d .
Use grep to search for lines of text that match one or many regular expressions, and outputs only the matching lines. Using the grep command, we can recursively search all files for a string on a Linux.
There are several possiblities:
Using find:
Using find to create a list of all files, and then piping them to sed
or the equivalent, as suggested in the answer you reference, is fairly straightforward, and only requires scanning through the files once.
You'd use one of the same answers as from the question you referenced, but adding -path '*/.svn' -prune -o
after the find .
in order to prune out the SVN directories. See this question for a discussion of using the prune
option with find
-- although note that they've got the pattern wrong. Thus, to print out all the files, you would use:
find . -path '*/.svn' -prune -o -type f -print
Then, you can pipe that into an xargs
call or whatever to do the individual replacements, as suggested in the question you referenced. There is a lot of discussion there about different options, which I won't reproduce here, although I prefer the version from John Zwinck's answer:
find . -path '*/.svn' -prune -o -type f -exec sed -i 's/foo/bar/g' {} +
Using recursive grep:
If you have a system with GNU grep, you can use that to find the list of files as well. This is probably less efficient than find, but it does allow you to only call sed
on the files that match, and I personally find the syntax a lot easier to remember (or figure out from manpages):
sed -i 's/foo/bar/g' `grep -l -R --exclude-dir='*/.svn' 'foo' .`
The -l
option causes grep to only output the list of file names, rather than the matching lines.
Using a GUI editor:
Alternately, if you're using windows, do what I do -- get a copy of the NoteTab editor (available in a free version), and use its search-and-replace-on-disk command, which ignores hidden .svn directories automatically and just works.
Edit: Corrected find pattern to */.svn
instead of .svn
, added more details and some other possibilities. However, this depends on your platform and svn version: .svn
without */
may be required in some cases, like on CentOS 7.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With