Skip to content

Replacing the full contents of a Subversion working (sub)dir

The annoyances that I suffered earlier today during the upgrade of a WordPress plugin made me turn to my favorite text-editor to create a simple script, svn-replace-dir:

usage() {
    cat <<"EOF"
$0 [--dry-run] <svn_dir> <replacement_dir>
This script replaces the contents of <svn_dir> with the contents of <replacement_dir>,
where <replacement_dir> is not an svn directory.
Copyleft 2010, Rowan Rodrik van der Molen <>
fatal_error() {
    echo -e "\e[1;31m$message\e[0m"
    exit 1
usage_error() {
    error="Wrong usage."
    if [ -n "$1" ]; then
    echo -e "\e[1;31m$error\e[0m"
    exit 1
run_command() {
    echo -e "\e[1;34m$1\e[0m"
    [ $dry_run == 1 ] || eval $1
if [ $1 == '--dry-run' ]; then
[ $# == 2 ] || usage_error "Wrong number of arguments."
svn_dir=`echo "$1"|sed -e 's#/$##'`
replacement_dir=`echo "$2"|sed -e 's#/$##'`
#if [ "${svn_dir:0:1}" != "/" ]; then svn_dir="$PWD/$svn_dir"; fi
#if [ "${replacement_dir:0:1}" != "/" ]; then replacement_dir="$PWD/$replacement_dir"; fi
[ -d "$svn_dir" ] || usage_error "$svn_dir is not a directory."
[ -d "$replacement_dir" ] || usage_error "$replacement_dir is not a directory."
# Create all subdirectories in $svn_dir that do not yet exist
cd $replacement_dir
find . -mindepth 1 -type d -print | sed -e 's#^./##' | while read d; do
    cd $begin_path/$svn_dir
    # Doesn't the destination directory already exist?
    if [ ! -d "$d" ]; then
        run_command "svn mkdir '$d'"
# Copy all files from $replacement_dir to $svn_dir
cd $begin_path/$replacement_dir
find . -type f -print | sed -e 's#^./##' | while read f; do
    cd $begin_path
    run_command "cp '$replacement_dir/$f' '$svn_dir/$f'" # FIXME: Quoting problem
# Remove all files that do no longer exist in $replacement dir
cd $begin_path/$svn_dir
find . -type f -print | grep -v '.svn' | while read f; do
    if [ ! -f "$begin_path/$replacement_dir/$f" ]; then
        run_command "svn rm '$f'"
# Remove all subdirs that do no longer exist in $replacement dir
cd $begin_path/$svn_dir
find . -mindepth 1 -type d -print | grep -v '.svn' | while read d; do
    if [ ! -d "$begin_path/$replacement_dir/$d" ]; then
        run_command "svn rm '$d'"
exit 0

Using the script is simple:

svn-replace-dir simple-tags new-simple-tags|less -R

It replaces all the contents of the first directory (simple-tags in the example) with those of the second directory and it deletes everything that is no longer present in the second dir. In the process, it does all the necessary calls to svn mkdir, svn rm and (in the next version) svn add.

diff tells me that the script has done its work correctly:

diff -x .svn -ruN simple-tags new-simple-tags
# Emptiness is bliss :-) 

This is another one of these occasions when Git would have made life so much easier. Luckily, at least there’s GitHub to host this script as a Gist. Check there if you want to fetch the newest version of this script.

    No Comments ( Add comment / trackback )