I find I often want to do some operation on files, while preserving their directory structure. For this reason I defined a bash function filtercmd
. This takes a list of files to operate on as stdin, and as parameters takes the operation (e.g. mv
) and the destination directory. Once I've done this I can do things like this as a simple one liner.
filtercmd () {
if [ ! -d "$2" ]; then echo "$2" does not appear to be a directory; return 1; fi
while read f; do
dir="${f%/*}"
if [ ! "$dir" = "$lastdir" ]
then mkdir -p "$2/$dir"; echo "$dir"; lastdir="$dir"; fi
[ -e "$2/$f" ] || $1 "$f" "$2/$f"; done
}
(cd /media/localbackup && find . | filtercmd "mv -vfb" /media/remotebackup)
This can also be done with rsync
. Using rsync
's remote protocol can save a lot of bandwidth since the protocol only needs to send changed chunks. However, two advantages of filtercmd
over rsync
are (1) that you can use your existing mv flags without learning the rsync equivalents and (2) and we can also use filtercmd
for more powerful things like:
(z(){ grep . <$1|gzip >$2.gz;};find . -name '*.txt' | filtercmd z ../gz })
Which selectively takes txt files, eliminates empty lines, and gzips them onto the destination directory.