diff options
author | Dominique Martinet <asmadeus@codewreck.org> | 2017-12-02 11:28:04 +0100 |
---|---|---|
committer | Dominique Martinet <asmadeus@codewreck.org> | 2017-12-02 11:28:04 +0100 |
commit | 920a5de091655d6df2761694199cdd4e15297b31 (patch) | |
tree | 0276203241097a78d068e97bb8ebc225e37c7c98 | |
parent | ac8bafef0d120e5092cfd2e4742640b572b864df (diff) |
handle arguments similarily to cp
-rwxr-xr-x | mcp.sh | 68 |
1 files changed, 57 insertions, 11 deletions
@@ -2,6 +2,11 @@ VERBOSE= +error() { + echo "ERROR: " "$@" + exit 1 +} + cp-dir() { local DST="$1" shift 1 @@ -38,20 +43,61 @@ fixstamp-dirs() { export -f fixstamp-dirs main() { - set -euo pipefail + local DEST="${*: -1}" + local DESTFD FINDSRC + local CREATED_DEST=0 BASESRC + set -- "${@:1:$(($#-1))}" umask 0077 - mkdir -p /tmp/dest - exec {DESTFD}</tmp/dest - local FINDSRC=$(mktemp /tmp/mcp-find-src.XXXXXXX) - trap "rm -f $FINDSRC" EXIT + # cp-like dest heuristic: + # create dest directory if it doesn't exist, unless multiple + # sources or single source ends in "/." + if [[ ! -d "$DEST" ]]; then + [[ "$#" == 1 ]] || error "$0: target '$DEST' is not a directory" + # Handle single file source separately... You're + # calling the wrong script + [[ -d "$1" ]] || exec cp -a${VERBOSE+v} "$1" "$DEST" + mkdir -p "$DEST" + CREATED_DEST=1 + fi + exec {DESTFD}<"$DEST" + # from here, use this FD as base for DEST + DEST="/proc/$$/fd/$DESTFD" - cd /tmp/tree - find . -type d -print0 > $FINDSRC - xargs -0 bash -c 'mk-dirs "$@"' -- /proc/$$/fd/$DESTFD < $FINDSRC - xargs -0 -P 8 -n 10 bash -c 'cp-dir "$@"' -- /proc/$$/fd/$DESTFD < $FINDSRC - xargs -0 -P 8 -n 10 bash -c 'fixstamp-dirs "$@"' -- /proc/$$/fd/$DESTFD < $FINDSRC + FINDSRC=$(mktemp /tmp/mcp-find-src.XXXXXXX) + # shellcheck disable=SC2064 + trap "rm -f '$FINDSRC'" EXIT + + for SRC in "$@"; do + # cp-like source heuristic: + # unless we just created DEST, create a new directory + # with source basename within it. + # Also get single files/etc out of the way first, don't + # use this script for that!! + if [[ ! -d "$SRC" ]]; then + cp -a "$SRC" "$DEST" + continue + fi + if ((CREATED_DEST)); then + cd "$SRC" + BASESRC=. + else + cd "$(dirname "$SRC")" + BASESRC=$(basename "$SRC") + fi + find "$BASESRC" -type d -print0 > "$FINDSRC" + xargs -0 bash -c 'mk-dirs "$@"' -- "$DEST" < "$FINDSRC" + xargs -0 -P 8 -n 10 bash -c 'cp-dir "$@"' -- "$DEST" < "$FINDSRC" + xargs -0 -P 8 -n 10 bash -c 'fixstamp-dirs "$@"' -- "$DEST" < "$FINDSRC" + done + + exec {DESTFD}<&- } -main +# if we're being sourced, don't actually run +[[ $(caller | cut -d' ' -f1) != "0" ]] && return 0 + +set -euo pipefail + +main "$@" |