make rsync wait for a confirmation before actually changing files
Solution 1:
In lieu of an official "--confirm" option, rsync's own "batch mode" can be leveraged to bypass having to twice compute the difference between two paths. Batch mode was intended for distributing changes to mirrors (compute once, update many identical trees). Two files are created: a batch file containing the updates and a simple convenience script for running the update (there's a section toward the end of the rsync man page with details).
Here's a bash wrapper for abstracting the process:
#!/bin/bash
cleanup ()
{
rm ${BFILE} ${BFILE}.sh &>/dev/null
}
# generate tmpfile
BFILE=$( mktemp )
# rsync command
if ! rsync --only-write-batch="${BFILE}" --verbose "$@"; then
cleanup
exit 1
fi
# confirmation
read -p "Continue (y/N)? " confirm
if [ "$confirm" != "y" ]; then
echo "Aborting"
cleanup
exit 1
fi
# carve up arguments
dest="${@: -1}" # last argument
host="${dest%%:*}" # host:path
path="${dest#*:}"
opts="${@:1:$(($#-2))}" # everything but the last two args
if [ "$host" = "${path}" ]; then
# local
sh "${BFILE}.sh"
else
# remote
ssh "$host" rsync --read-batch=- "${opts}" "${path}" <"${BFILE}"
fi
cleanup
Note that since this script writes to $TMP_DIR
, you might run into space constraints if you are moving really big data (larger than your /tmp, for instance).
Solution 2:
You can use the -n option with rsync to perform a dry run. rsync will tell you what operations it would have performed without actually doing them. If you're happy with the results, re-run without the -n option.
Solution 3:
You may make rsync to backup files on overwrite, using --backup option,
-b, --backup make backups (see --suffix & --backup-dir)
--backup-dir=DIR make backups into hierarchy based in DIR
--suffix=SUFFIX backup suffix (default ~ w/o --backup-dir)
after rsync run you can scan backup-dir for files and ask one by one if it need to be restored.
Solution 4:
Sadly, there is no built in method in Rsync at the time writing.
Mike Fitzpatrick's solution will work fine, however if you have a very large directory tree, you may want to do something that doesn't make rsync go through all the files again
EDIT: There is also a bug where it wont delete a destination file... the more and more I look at it, this solution is broken... I am leaving it up becase it may work in your case and also if someone wants to fix it. Also, someone should submit a formal feature request to https://bugzilla.samba.org/enter_bug.cgi?product=rsync
I wrote this script:
#! /bin/bash
# Make a temp file for storing the output of rsync
tmpfile=$( mktemp ) &&
# Do all the hard work ( get the list of files we need to update ),
# but dont actually change the filesystem
rsync --dry-run --out-format='RSYNC_CONFIRM %i %n%L' "$@" | grep RSYNC_CONFIRM | awk '{ print $3 }' > $tmpfile &&
# Output to the user what we propose to do
rsync --dry-run --itemize-changes --files-from=$tmpfile "$@" &&
# Alternatively, we could just output $tmpfile... but whatever...
read -p "Continue? (y/n)?" &&
if [[ $REPLY = [yY] ]]
then
{
rsync --files-from=$tmpfile "$@"
}
fi
rm $tmpfile
Try pasting the script into a file called
rsync-confirm.bash
Then
chmod +x rsync-confirm.bash
Then
./rsync-confirm.bash -rvh /etc/ /tmp/etc/
This script might be a little buggy, I noticed that it doesn't really like it if you don't have a trailing slash on the source directory...