Merging directories in command line in Linux is a pain because the native mv
command will not allow recursive overwriting. So if we want to merge two directories, a lot of people like to suggest either using cp
or rsync
to copy over files and then delete the source files. Another way is to use a shell command to recursively run the move operation on each file in the source directory and mv
it to the destination directory/subdirectory. I like this approach more because then you can add in arbitrary rules for which files to copy.
In the example below, we are doing the following for each file found in the src
directory:
1. Checking that the subdirectory exists in the target (dst
) destination. If it does not exist, then we create a new directory.
2. If the file does not exist in the target, then just move it.
3. Otherwise if the file exists in the source, we then are checking if the file size for the source (fsizeSrc
) is larger than or equal to the destination file size (fsizeDst
). If true, then we mv
the file over the destination file.
[This is a repurposing of Alex’s post on Linux – Copy only new and larger files – Super User]
#!/bin/bash
### Purpose:
# Move huge amount of files from source to destination directory only if
# destination file is smaller in size or the same size as in source directory
###
src='/sourcedirectory' # Source directory
dst='/destinationdirectory' # Destination directory
icp() {
f="${1}";
[ -d "$f" ] && {
[ ! -d "${dst}${f#$src}" ] && mkdir -p "${dst}${f#$src}" && echo "created dir: ${dst}${f#$src}";
return
}
[ ! -f "${dst}/${f#$src/}" ] && { mv "${f}" "${dst}/${f#$src/}" && echo "moved file: ${f}"; return; }
fsizeSrc=$( stat -c %s "$f" )
fsizeDst=$( stat -c %s "${dst}/${f#$src/}" )
[ ${fsizeDst} -lt ${fsizeSrc} ] || [ ${fsizeDst} -eq ${fsizeSrc} ] && mv "${f}" "${dst}/${f#$src/}" && echo "overwrote file ${f} ${dst}/${f#$src/}"
}
export -f icp
export src
export dst
find ${src} -exec bash -c 'icp "$0"' {} \;