#!/bin/bash

#https://serverfault.com/questions/566774/whats-the-best-way-to-merge-two-directories-on-the-same-filesystem-in-linux

# There's a case where mv fails. Here's some example data:

# mkdir -p src/d dest/d
# touch src/d/f1 dest/d/f2
# See how mv fails:
# $ mv src/* dest/
# mv: cannot move 'src/d' to 'dest/d': Directory not empty
# $ mv -f src/* dest/
# mv: cannot move 'src/d' to 'dest/d': Directory not empty
# $ mv -fv src/* dest/
# mv: cannot move 'src/d' to 'dest/d': Directory not empty
# $ mv -fvi src/* dest/
# mv: overwrite 'dest/d'? y
# mv: cannot move 'src/d' to 'dest/d': Directory not empty
# $ mv -fvi -t dest/ src/*      
# mv: overwrite 'dest/d'? y
# mv: cannot move 'src/d' to 'dest/d': Directory not empty

# So make a script file:
# vim supermove
# This example does no error checking (DISCLAIMER: works for me, but please test that it works for you... maybe with echo before mv), and will overwrite files with same path. And it uses find with \; which is terribly inefficient, but + doesn't work right with "$dest" prepended. Older versions will make some dirs without the path prepended, and newer versions of find will say:
# find: In '-exec ... {} +' the '{}' must appear by itself, but you specified 'dest/{}'
# You could probably find a way to fix that with xargs though. (It took a few minutes on the 64k files 8TB that I was moving). Add this content:



src=$1
dest=$2

src=$(readlink -f "$src")
dest=$(readlink -f "$dest")

cd "$src"

# also copy hidden files
shopt -s dotglob

# make dirs (missing old permission,acl,xattr data), and then mv the files
time find * -type d -exec mkdir -p "$dest"/{} \;
time find * -type f -exec mv {} "$dest"/{} \;

# also copy permissions, acls, xattrs
rsync -aAX "$src"/ "$dest"/