Skip to content
Snippets Groups Projects
Verified Commit 677dbeb9 authored by Renato Alves's avatar Renato Alves :seedling:
Browse files

ENH Add 'mv_keep_parents'

parent 3f1a355f
No related branches found
No related tags found
No related merge requests found
......@@ -17,6 +17,8 @@ EMBL utilities
``qs`` - collect queue status across different SGE clusters/queues. Requires key-based authentication with SSH.
``mv_keep_parents`` - equivalent to ``cp --parents src/*.txt dest/`` but moving instead of copying. Optionally keeping source directories if empty with option ``-k``.
Examples
========
......
#!/usr/bin/env bash
ERROR="ERROR:"
KEEPDIRS=0
VERBOSE=0
DRYRUN=""
usage() {
echo >&2 ""
echo >&2 "Usage:"
echo >&2 " $0 [-k] source1 [source2 [...]] destination"
echo >&2 ""
echo >&2 "Will move files from all specified sources to destination"
echo >&2 "while preserving the folder structure of each source"
echo >&2 ""
echo >&2 "Options:"
echo >&2 " -k --keepdirs = keep source directories even if empty. Defaults to removing if empty"
echo >&2 " -d --dryrun = simulate execution without performing actions on the filesystem"
echo >&2 " echoes most actions that would be performed"
echo >&2 " removal of empty directories isn't simulated"
echo >&2 " -v --verbose = echo verbose info while executing. Defaults to non-verbose execution"
echo >&2 ""
echo >&2 "Example:"
echo >&2 " $0 path/to/*.txt destination -> destination/path/to/*.txt"
echo >&2 ""
}
move_preserve_path() {
parent="$(dirname "$1")"
$DRYRUN mkdir -p "$2/$parent"
$DRYRUN mv "$1" "$2/$parent"
if [ "$3" -eq 0 ]; then
empty_dir_remove_recurse "$parent"
fi
}
empty_dir_remove_recurse() {
# If the dir to remove is the current, don't even try
if [ "$1" == "." ] || [ "$1" == "$(pwd)" ]; then
return 0
fi
# Remove original directory if empty (recurses path backwards)
if [ -z "$(ls -A "$1")" ]; then
$DRYRUN rmdir "$1"
empty_dir_remove_recurse "$(dirname "$1")"
fi
}
generic_error() {
usage
echo >&2 "${ERROR} $1"
echo >&2 ""
exit 1
}
ARG_PARSE="getopt -o vkdh -l verbose,keepdirs,dryrun,help -n $0 --"
# We process arguments twice to handle any argument parsing error:
ARG_ERROR=$($ARG_PARSE "$@" 2>&1 1>/dev/null)
if [ $? -ne 0 ]; then
generic_error "$ARG_ERROR"
fi
# Abort on any errors from this point onwards
set -euo pipefail
# Parse args using getopt (instead of getopts) to allow arguments before options
ARGS=$($ARG_PARSE "$@")
# reorganize arguments as returned by getopt
eval set -- "$ARGS"
while true; do
case "$1" in
# Shift before to throw away option
# Shift after if option has a required positional argument
-v|--verbose)
shift
VERBOSE=1
;;
-k|--keepdirs)
shift
KEEPDIRS=1
;;
-d|--dryrun)
shift
DRYRUN="echo"
;;
-h|--help)
shift
usage
exit 1
;;
--)
shift
break
;;
esac
done
if [ "$#" -lt 2 ]; then
generic_error "$0 requires at least 2 arguments - source and destination"
fi
# enable verbose execution
if [ "$VERBOSE" -eq 1 ]; then
set -euxo pipefail
fi
DEST="${!#}"
if [ ! -d "$DEST" ]; then
generic_error "Destination $DEST doesn't exist"
fi
while [ "$#" -ge 2 ]; do
SRC="$1"
shift
move_preserve_path "$SRC" "$DEST" "$KEEPDIRS"
done
# vim: ai sts=4 et sw=4
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment