A bash shell script to find-and-replace in all files in multiple svn repositories.
Here is what I wanted the script to do:
- Prompt the user for the value to find
- Prompt the user for the value to replace the “find” value with
- Prompt the user for the SVN commit message
- For each repository, check out and update a working copy on my machine, then do the find and replace, and finally, commit the changes to the SVN server
Walkthrough
The first thing I needed to do was to define some constant variables to hold some values, such as the root SVN URL, the path to store the working copies, and the names of all of the repositories.
# Define constants
BASE_URL="http://svn.example.com/"
ROOT="/Users/brian/repos/"
REPOSITORIES=("Access" "Accessibility" "Adobe" "Ajax" "Apache" "CSS")
The next thing I do is prompt the user for the necessary values.
I am then escaping the find
and replace
values for any special regular expression characters.
# Prompt the user for the find value
read -p "What value would you like to replace? " find
find_regex=$(echo "${find}"|sed 's!\([]\*\.\$\/&[]\)!\\\1!g')
# Prompt the user for the replace value
read -p "What value do you want to replace this with? " replace
replace_regex=$(echo "${replace}"|sed 's!\([]\*\.\$\/&[]\)!\\\1!g')
# Prompt the user to enter the commit message
read -p "Enter a commit message for all updates: " commit_message
Now it’s time to loop over each of the repositories. Doing the svn checkout and update is easy enough, but the find and replace was a little tricky.
- First I use the grep command to get a list (character return delimited) of paths to files that contain the
find
value - I then pipe the results of the grep command to the xargs command, which will call the sed command for each file in the list
- The sed command uses the following flags:
- -i to do the replacement inline. Note, Mac OS X uses a BSD version of the sed command that requires a value for the -i argument. In this case I am just using an empty string so that no backup files are generated.
- -e to specify the command. The command starts with “s/” to tell sed to substitute the
find
values with thereplace
values. The command also includes the “g” flag so that the find and replace is made globally throughout the file
- The last thing we need to do is to commit the changes to the repository.
# Loop over each repository
for i in "${REPOSITORIES[@]}"
do
#set variables for each iteration
url="${BASE_URL}${i}/trunk"
path="${ROOT}${i}"
#do checkout
echo "checkout: ${url}"
svn checkout "${url}" "${path}"
#do find and replace
echo "replacing '${find}' with '${replace}'"
grep -lr --exclude-dir=".svn" -e "${find}" "${path}" | xargs sed -i '' -e "s/${find_regex}/${replace_regex}/g"
#do commit
echo "committing"
svn commit -m "${commit_message}" "${path}"
done
Complete Script
#!/bin/bash
# Define constants
BASE_URL="http://svn.example.com/"
ROOT="/Users/brian/repos/"
REPOSITORIES=("Access" "Accessibility" "Adobe" "Ajax" "Apache" "CSS")
# Prompt the user for the find value
read -p "What value would you like to replace? " find
find_regex=$(echo "${find}"|sed 's!\([]\*\.\$\/&[]\)!\\\1!g')
# Prompt the user for the replace value
read -p "What value do you want to replace this with? " replace
replace_regex=$(echo "${replace}"|sed 's!\([]\*\.\$\/&[]\)!\\\1!g')
# Prompt the user to enter the commit message
read -p "Enter a commit message for all updates: " commit_message
# Let the user know we are starting
echo "Thanks. We are going to replace all instances of '${find}' with '$replace'."
echo "OK, let's check out all of the SVN repositories. Please be patient..."
# Loop over each repository
for i in "${REPOSITORIES[@]}"
do
#set variables for each iteration
url="${BASE_URL}${i}/trunk"
path="${ROOT}${i}"
#do checkout
echo "checkout: ${url}"
svn checkout "${url}" "${path}"
#do find and replace
echo "replacing '${find}' with '${replace}'"
grep -lr --exclude-dir=".svn" -e "${find}" "${path}" | xargs sed -i '' -e "s/${find_regex}/${replace_regex}/g"
#do commit
echo "committing"
svn commit -m "${commit_message}" "${path}"
done
Download
If you would like to download the full script, here you go:
Just extract the zip and set it to be executable:
$ chmod +x find-and-replace.sh