Created
November 3, 2023 06:54
-
-
Save massenz/102d0a3cfe3a51eebd27d5c1c7088a58 to your computer and use it in GitHub Desktop.
Shell script to archive & encrypt folders
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env zsh | |
# | |
# Snapshot archive of all contents in the folder defined in a variable | |
# called $SOURCE, using $TAR_OPTS tar options. | |
# | |
# Created MM, 2012-01-21 | |
# Revised MM, 2023-11-03 | |
set -eu | |
source ${COMMON_UTILS}/utils | |
BASEDIR=$(abspath $(dirname $0)) | |
function usage { | |
printf "Usage: %s [-n | -h] DEST SOURCES\n\n" $(basename "$0") | |
cat << EOF | |
Snapshot archive of all contents in the SOURCE folder, using \$TAR_OPTS tar options. | |
If the -n flag is specified, it will abort if the destination file (or its | |
encrypted version) are already present. | |
Requires a virtualenv called 'crytto' with this package installed (pip install crytto) | |
Options: | |
-n Non-interactive mode. Abort if the destination file already exists. | |
-h Prints this help and exits | |
Arguments: | |
SOURCES Required. The source folders to archive and encrypt. | |
DEST Required. Destination path for the encrypted archive: omit any | |
file extension, .tar.gz.enc will be automatically appended | |
EOF | |
} | |
function check_mount { | |
local tag="$1" | |
if [[ ! -e "$tag" ]]; then | |
msg "Attempting to mount destination folder ${DEST}" | |
mount $DEST | |
if [[ ! -e "$tag" ]]; then | |
fatal "No tag file [${tag}] on ${DEST}, aborting" | |
fi | |
fi | |
} | |
function validate { | |
local file_extension_regex='^.+\.[^.]+$' | |
if [[ ! -x $(which filecrypt) ]]; then | |
fatal "Missing filecrypt executable in virtualenv ${VENV}" | |
fi | |
if [[ -z ${SOURCES} ]]; then | |
fatal "At least one SOURCE folder must be specified" | |
fi | |
if [[ ${DEST} =~ ${file_extension_regex} ]] | |
then | |
usage | |
fatal "DEST should have no extension" | |
fi | |
if [[ -e ${DEST}.tar.gz.enc ]]; then | |
if [[ ${ASK} == "n" ]]; then | |
fatal "Encrypted archive $(basename ${DEST}) already exists, aborting" | |
fi | |
read -p "File ${DEST}.tar.gz.enc already exists, overwrite? [y/N] " overwrite | |
if [[ $overwrite != 'y' ]]; then | |
fatal "Snapshot canceled" | |
fi | |
fi | |
} | |
declare ASK="y" | |
while getopts ":hn" opt; do | |
case ${opt} in | |
h) | |
usage | |
exit 0 | |
;; | |
n) | |
ASK="n" | |
;; | |
\?) | |
echo "Invalid option: -$OPTARG" >&2 | |
usage | |
exit 1 | |
;; | |
esac | |
done | |
shift $((OPTIND -1)) | |
if [[ ${ASK} == "n" ]]; then | |
msg "Non-Interactive option given (-n)" | |
fi | |
if [[ $# < 2 ]] | |
then | |
usage | |
fatal "Not enough arguments" | |
fi | |
declare -r DEST="${1:-}" | |
shift 1 | |
declare -r SOURCES=$@ | |
declare -r TMP_DIR=$(mktemp -d) | |
declare -r TAG="$(dirname ${DEST})/tag" | |
declare -r TARBALL="${TMP_DIR}/$(basename ${DEST}).tar.gz" | |
declare -r VENV="crytto" | |
# Activates Virtualenv with the `crytto` module installed | |
source ${WORKON_HOME}/${VENV}/bin/activate | |
validate | |
check_mount $TAG | |
msg "Archiving files in ${SOURCES}: creating snapshot in ${DEST}" | |
msg "Creating temporary plaintext tarball in ${TARBALL}" | |
if [[ ! -f ${TARBALL} ]] | |
then | |
# We deactivate exit-on-error, as tar will throw some errors | |
# which are safe to ignore. | |
set +e | |
# We use J (xz compression) instead of z (gzip), as apparently | |
# it should provide better compression. | |
sudo tar caJf "${TARBALL}" ${TAR_OPTS} ${SOURCES} | |
set -e | |
else | |
msg "${TARBALL} exists, skipping archive" | |
fi | |
if [[ ! -f "${TARBALL}" ]] | |
then | |
fatal "Failed to create snapshot" | |
fi | |
sudo chown ${USER}:users "${TARBALL}" | |
msg "Encrypting ${TARBALL} to ${TARBALL}.enc" | |
filecrypt -o ${TARBALL}.enc ${TARBALL} | |
msg "Moving ${TARBALL}.enc to ${DEST}" | |
mv "${TARBALL}.enc" "${DEST}.tar.gz.enc" | |
success "Created snapshot archive $(ls ${DEST}*)" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment