Skip to content

Instantly share code, notes, and snippets.

@antichris
Last active September 20, 2023 03:00
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save antichris/145573b70179c61f4b7fd7e9996eb98e to your computer and use it in GitHub Desktop.
Save antichris/145573b70179c61f4b7fd7e9996eb98e to your computer and use it in GitHub Desktop.
A POSIX-compliant recursive "mv --update", like "cp -ru" but moving instead of copying.
#!/bin/sh
## This Source Code Form is subject to the terms of the Mozilla Public
## License, v. 2.0. If a copy of the MPL was not distributed with this
## file, You can obtain one at https://mozilla.org/MPL/2.0/.
usage=$(cat) <<***
Usage: $0 SOURCE DEST
Perform a recursive "mv -u", like "cp -ru" but moving instead of copying.
--help display this help and exit
If SOURCE is a file, this will simply invoke "mv -u" (move when the SOURCE file
is newer than the destination file or when the destination file is missing).
If SOURCE is a directory, this will check whether DEST exists. If it does not,
"mv -u" will be invoked. Otherwise, each entry of SOURCE is processed
recursively as described above.
***
main() {
for arg; do
[ "$arg" = '--help' ] && dieWithUsage
done
if [ ! "$2" ]; then
dieWithUsage 1 'DEST argument required'
fi
if [ ! -e "$1" ]; then
dieWithUsage 1 'SOURCE does not exist'
fi
recurse "$1" "$2"
}
dieWithUsage() {
[ "$2" ] && printf %s\\n "$2" >&2
printf '%s\n' "$usage"
exit "${1:-0}"
}
recurse() {
if [ ! -d "$1" ] || [ ! -e "$2" ]; then
mv -u "$1" "$2" || exit
return
fi
for entry in "$1/"* "$1/."[!.]* "$1/.."?*; do
if [ -e "$entry" ]; then
recurse "$entry" "$2/${entry##"$1/"}"
fi
done
}
main "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment