#!/bin/sh
# Replicates a directory with minimal space: all files are hardlinked,
# rest is copied.
#(c) Hans-Peter-Stoerr (www.stoerr.net) Jan 2004
#$Id: hardlndir,v 1.1 2004/01/08 08:26:34 stoerr Exp $
fromdir=$1
todir=$2
if test -z "$2"; then
   echo $0: usage: $0 fromdir todir
   echo replicates fromdir to todir by hardlinking files
   exit 3
fi
mkdirhier "$todir" || exit 3

#create all directories
find "$fromdir" -mindepth 1 -type d -printf '%P\000' \
| (cd "$todir"; xargs -r -0 mkdir -p)

#(hard)link all files
# This is not entirely correct: it would not link
# dirnames with newlines. But bash seems to have a bug
# when we do something like
# find . -print0 | (while read -d '\000' -r fn; do echo $fn; done)
find "$fromdir" -type d -printf '%P\n' \
| ( while read -r dirname; do
    find "$fromdir/$dirname" -mindepth 1 -maxdepth 1 -type f -print0 \
    | xargs -r -0 ln -f "--target-directory=$todir/$dirname"
    done )

#Copy symlinks
# TODO: doesn't handle names with newlines so far.
#       What the heck, rsync does this afterwards
set -x
find "$fromdir" -type l -printf '%l\n%P\n' \
| (while read -r linkto; do read -r link; ln -s "$linkto" "$link"; done)

#catch all: copy the rest, correct dirtimes
rsync -axHSW "$fromdir/." "$todir/."
