#!/bin/sh RED="$(printf '\033[38;5;9m')" RESET="$(printf '\033[m')" set -euf BN="${0##*/}" export POSIXLY_CORRECT=1 if [ -n "${NO_COLOR:-}" ]; then RED="" RESET="" fi errecho() { >&2 echo "$*$RESET" } fail() { errecho "${RED}error: $BN: $RESET$*" exit 1 } _type() { type "$@" >/dev/null 2>&1 ; } usage() { cat >&2 <<-EOF usage: $BN -e (-r RECIPIENT | -R PATH)... [-a] [-o OUTPUT] [--] FILES... $BN -e -p [-a] [-o OUTPUT] [--] FILES... $BN -d [-i PATH]... [-o OUTPUT] [--] FILES... options: -e encrypt the input files to an output tar -d decrypt the input tar to output files -o OUTPUT encrypting: write output tar to OUTPUT. stdout if omitted decrypting: directory to extract to. PWD if omitted -a encrypt to a PEM encoded format -p encrypt with a passphrase -r RECIPIENT encrypt to the specified RECIPIENT. can be repeated -R PATH encrypt to the recipients listed at PATH. can be repeated -i PATH decrypt using the identity file at PATH. can be repeated at least one FILE is required for both encrypting and decrypting if multiple are present, each will be processed with the same identities you probably want an OUTPUT when encrypting, even if it's not required (age will yet at you for that anyway unless you also use -a) most of these options are passed directly to age(1). see its man page for more details. EOF } AGEOPTS= RECIPIENTS= RECIPIENTS_FILES= IDENTITIES= while getopts :hedo:apr:R:i: OPT; do case $OPT in h) usage && exit 0 ;; e) TYPE=e; AGEOPTS="$AGEOPTS -e" ;; d) TYPE=d; AGEOPTS="$AGEOPTS -d" ;; o) [ -z "${OUTPUT:-}" ] && OUTPUT="$OPTARG" || fail "don't specify output twice D:" ;; a) AGEOPTS="$AGEOPTS -a" ;; p) AGEOPTS="$AGEOPTS -p" ;; r) RECIPIENTS="$RECIPIENTS -r '$(printf '%s' "$OPTARG" | sed -e "s/'/'\\\\''/g")'" ;; R) RECIPIENTS_FILES="$RECIPIENTS_FILES -R '$(printf '%s' "$OPTARG" | sed -e "s/'/'\\\\''/g")'" ;; i) IDENTITIES="$IDENTITIES -i '$(printf '%s' "$OPTARG" | sed -e "s/'/'\\\\''/g")'" ;; *) ;; esac done shift $((OPTIND - 1)) [ "$#" -lt 1 ] && usage && exit 1 [ -z "${TYPE:-}" ] && fail 'specify one of -e or -d' TAR="$(mktemp)" trap 'rm "$TAR"' INT HUP QUIT EXIT if [ "$TYPE" = "e" ]; then { _type bsdtar && CMD="bsdtar -rL -f"; } || \ { _type tar && CMD="tar -rh -f"; } || \ fail "can't find tar command!" for f; do if [ -f "$f" ] || [ -d "$f" ]; then $CMD "$TAR" "$f" >/dev/null 2>&1 else errecho "$f is not a regular file or directory! skipping..." fi done eval 'age $AGEOPTS ${OUTPUT:+-o "$OUTPUT"} '"$RECIPIENTS $RECIPIENTS_FILES $IDENTITIES"' "$TAR"' else { _type bsdtar && CMD="bsdtar -x -f"; } || \ { _type tar && CMD="tar -x -f"; } || \ fail "can't find tar command!" for f; do eval 'age $AGEOPTS -o "$TAR" '"$RECIPIENTS $RECIPIENTS_FILES $IDENTITIES"' "$f"' [ ! -d "${OUTPUT:="$PWD"}" ] && mkdir -p "$OUTPUT" $CMD "$TAR" -C "$OUTPUT" done fi