Skip to content

Instantly share code, notes, and snippets.

@xtavras
Created August 19, 2026 13:19
Show Gist options
  • Select an option

  • Save xtavras/4ab96664c26851e7d6b8ca4961c77fa2 to your computer and use it in GitHub Desktop.

Select an option

Save xtavras/4ab96664c26851e7d6b8ca4961c77fa2 to your computer and use it in GitHub Desktop.
archiver.sh encrypt folders with 7zip file
#!/usr/bin/env bash
# Archive a folder into an encrypted .7z file (AES-256, encrypted headers).
# Usage: archiver.sh [options] <folder>
#
# By default the folder is stored without compression. The archive is named
# after the folder (e.g. "archiver.sh myfolder" -> myfolder.7z) and written to
# the current directory unless --output is given.
#
# The password is read interactively. If the ARCHIVER_PW environment variable
# is set, its value is used automatically (handy for scripting/automation).
set -euo pipefail
# Locate a 7-Zip binary. Prefer the official "7zz" (brew install sevenzip),
# fall back to "7z" from p7zip (brew install p7zip).
SEVENZIP=""
for cmd in 7zz 7z; do
if command -v "$cmd" &> /dev/null; then
SEVENZIP="$cmd"
break
fi
done
if [ -z "${SEVENZIP}" ]; then
echo "Error: 7-Zip is not installed or not in your PATH." >&2
echo "Install it with: brew install sevenzip (or: brew install p7zip)" >&2
exit 1
fi
usage() {
cat <<EOF
Usage: $0 [options] <folder>
Archive a folder into an encrypted .7z file. Encryption is AES-256 with
encrypted headers (file names are hidden). You are prompted for the password
unless the ARCHIVER_PW environment variable is set.
Options:
-o, --output <path> Output location. If it ends with .7z it is used as the
archive filename, otherwise it is treated as a target
directory and <folder>.7z is written inside it.
Default: <folder>.7z in the current directory.
-c, --compress Use balanced compression (level 5). Default is store
only (no compression, level 0).
-h, --help Show this help message.
Environment variables:
ARCHIVER_PW If set, this password is used automatically instead of
prompting. Example: export ARCHIVER_PW=secret
Note: with this set, the password is passed on the
7-Zip command line and may be visible to other users
in the process list. Prefer the interactive prompt on
shared machines.
Examples:
$0 myfolder # -> ./myfolder.7z (no compression)
$0 --compress myfolder # -> ./myfolder.7z (balanced compression)
$0 -o /backups myfolder # -> /backups/myfolder.7z
$0 -o /backups/data.7z myfolder # -> /backups/data.7z
export ARCHIVER_PW=secret; $0 myfolder # non-interactive password
EOF
exit 1
}
# Parse arguments.
OUTPUT=""
COMPRESS_LEVEL=0
FOLDER=""
while [ $# -gt 0 ]; do
case "$1" in
-o|--output)
if [ $# -lt 2 ]; then
echo "Error: '$1' requires a path argument" >&2
exit 1
fi
OUTPUT="$2"
shift 2
;;
-c|--compress)
COMPRESS_LEVEL=5
shift
;;
-h|--help)
usage
;;
-*)
echo "Error: Unknown option '$1'" >&2
echo >&2
usage
;;
*)
if [ -n "${FOLDER}" ]; then
echo "Error: Only one folder can be given (got '${FOLDER}' and '$1')" >&2
exit 1
fi
FOLDER="$1"
shift
;;
esac
done
if [ -z "${FOLDER}" ]; then
echo "Error: No folder specified" >&2
echo >&2
usage
fi
if [ ! -d "${FOLDER}" ]; then
echo "Error: '${FOLDER}' is not a directory" >&2
exit 1
fi
# Derive the archive name from the folder (strips any trailing slash).
BASENAME="$(basename "${FOLDER}")"
# Resolve the output archive path.
if [ -z "${OUTPUT}" ]; then
ARCHIVE="${BASENAME}.7z"
elif [ "${OUTPUT%.7z}" != "${OUTPUT}" ]; then
# Ends with .7z -> use as the full archive filename.
ARCHIVE="${OUTPUT}"
else
# Treat as a directory.
if [ ! -d "${OUTPUT}" ]; then
echo "Error: Output directory '${OUTPUT}' does not exist" >&2
exit 1
fi
ARCHIVE="${OUTPUT%/}/${BASENAME}.7z"
fi
if [ -e "${ARCHIVE}" ]; then
echo "Error: '${ARCHIVE}' already exists" >&2
exit 1
fi
# Build the 7-Zip arguments.
# -t7z 7z format (required for AES-256 + header encryption)
# -mhe=on encrypt headers (hide file names)
# -mx=N compression level (0 = store, 5 = balanced)
# Password handling: a bare -p makes 7-Zip prompt and verify, so the password
# never touches the process list. If ARCHIVER_PW is set, use it non-interactively.
SEVENZIP_ARGS=(a -t7z -mhe=on "-mx=${COMPRESS_LEVEL}")
if [ -n "${ARCHIVER_PW:-}" ]; then
echo "Using password from ARCHIVER_PW environment variable."
SEVENZIP_ARGS+=("-p${ARCHIVER_PW}")
else
SEVENZIP_ARGS+=(-p)
fi
echo "Creating ${ARCHIVE} (compression level ${COMPRESS_LEVEL}, AES-256, encrypted headers)..."
"${SEVENZIP}" "${SEVENZIP_ARGS[@]}" -- "${ARCHIVE}" "${FOLDER}"
echo "Done: ${ARCHIVE}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment