Created
August 19, 2026 13:19
-
-
Save xtavras/4ab96664c26851e7d6b8ca4961c77fa2 to your computer and use it in GitHub Desktop.
archiver.sh encrypt folders with 7zip file
This file contains hidden or 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 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