How to fix Dropbox conflicts automatically

March 6, 2015 | |Source Code

If you use Dropbox regularly, you have probably managed to screw it up at some point by modifying a file on two machines without syncing it between edits. When this happens, Dropbox will save both versions of the file and rename one of them like so:

manifesto.txt
manifesto (Work Macbook's conflicted copy 2014-10-22).txt 

Sometimes these files are genuinely different and need to be reconciled manually, but more than a few times I've ended up with conflicts where Dropbox is just confused into thinking files are new when they're not. (This tends to happen if I'm working offline for an extended period on my laptop while my Desktop at work is still online.) In that case, I just want to find every pair of duplicated files and keep the newer one.

You can do this manually for small conflicts. For deep file structures like .git directories, it becomes a painful way to spend a Thursday night (if a rather effective way to learn about the Git file structure).

Using this Stack Overflow post as a starting point, I wrote a Bash script to find every conflicted file in a Dropbox directory and resolve it to the newer of the two files, backing up the older one.

Buyer's beware: It's never a great idea to download Bash scripts from strangers and just run them. I've attempted to save you from yourself by making this script execute in "dry run" mode by default, but you should look over this script before running it.

# get the script
git clone https://gist.github.com/40c0b8bf7ecba5a301f6.git
cd 40c0b8bf7ecba5a301f6
# make it executable
chmod 700 dropbox.sh
# execute it, but AFTER reading this post
./dropbox.sh

If you look at the script, you'll see you need to point it manually to your Dropbox instance and choose a place to back up the files that will be moved out of the Dropbox directory. The script will create this path for you if it doesn't exist.

#Point to where you want the script to look and where it should backup files it replaces
folder=~/Dropbox/Private
backup=~/Desktop/Dropbox.backup

The bulk of the script just scans every file and identifies each one that matches the Dropbox naming convention for conflicted files. It then compares the conflicted version and the regular one and keeps the newer one (removing the conflict language in the filename, of course).

As you see, the script doesn't actually move or name anything unless you pass "replace" as the first argument to the script. Otherwise, it's just a dry run.

find $folder -type f -print0 | while read -d $'\0' file; do
    newname=$(echo "$file" | sed 's/ (.*conflicted copy.*)//')

    if [ "$file" != "$newname" ]; then
        if [ -f "$newname" ];then
            # determine which is newer
            if [ "$newname" -nt "$file" ]; then
                echo "$newname is NEWER than $file"
                file_to_move="$file"
                file_to_keep="$newname"
            else
                echo "$newname is OLDER than $file"
                file_to_move="$newname"
                file_to_keep="$file"
            fi

            backupname=${newname/"$folder"/"$backup"}

            if [[ $1 != "replace" ]]; then
                echo "Would have moved $file_to_move to $backupname"
            else
                echo "Moving $file_to_move to $backupname"
                mkdirp "$(dirname "$backupname")"
                cp "$file_to_move" "$backupname"
                mv "$file_to_keep" "$newname"
            fi
        else
            # if the unconflicted version isn't there for some reason, just rename the original
            if [[ $1 != "replace" ]]; then
                echo "Didn't see an unconflicted counterpart for $file, so would have just renamed file"
            else
                echo "Didn't see an unconflicted counterpart for $file, so will replace"
                mv "$file" "$newname"
            fi
        fi
    fi
done

Gist here, edits welcome. If you're ready to run, just say ./dropbox.sh replace