summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDominique Martinet <asmadeus@codewreck.org>2017-12-02 11:28:04 +0100
committerDominique Martinet <asmadeus@codewreck.org>2017-12-02 11:28:04 +0100
commit920a5de091655d6df2761694199cdd4e15297b31 (patch)
tree0276203241097a78d068e97bb8ebc225e37c7c98
parentac8bafef0d120e5092cfd2e4742640b572b864df (diff)
handle arguments similarily to cp
-rwxr-xr-xmcp.sh68
1 files changed, 57 insertions, 11 deletions
diff --git a/mcp.sh b/mcp.sh
index 7653a23..ef659e8 100755
--- a/mcp.sh
+++ b/mcp.sh
@@ -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 "$@"