Skip to content

Instantly share code, notes, and snippets.

@sgomez
Created February 12, 2026 06:49
Show Gist options
  • Select an option

  • Save sgomez/12b6717a77254b7d3560c36adcce16fb to your computer and use it in GitHub Desktop.

Select an option

Save sgomez/12b6717a77254b7d3560c36adcce16fb to your computer and use it in GitHub Desktop.
Shell script to decrypt pdf files
#!/usr/bin/env bash
set -euo pipefail
# Decrypt encrypted PDFs matched by a glob pattern.
# - If a file is not encrypted, it is left unchanged.
# - If a file is encrypted, it is decrypted using the provided password.
# The original is preserved as "<name>.orig.pdf" and the decrypted output
# replaces the original filename.
# ---- Dependency check (qpdf) ----
if ! command -v qpdf >/dev/null 2>&1; then
cat >&2 <<'EOF'
ERROR: Required tool 'qpdf' is not installed.
Install on Ubuntu/Debian:
sudo apt update && sudo apt install -y qpdf
Install on Fedora:
sudo dnf install -y qpdf
Install on Arch:
sudo pacman -S qpdf
Install on macOS (Homebrew):
brew install qpdf
EOF
exit 127
fi
# ---- Usage ----
if [[ $# -ne 1 ]]; then
cat >&2 <<'EOF'
Usage:
decrypt_pdfs.sh "<glob-pattern>"
Example:
decrypt_pdfs.sh "*2025*.pdf"
EOF
exit 2
fi
pattern="$1"
# Expand the glob pattern safely, preserving spaces in filenames.
# compgen prints one match per line; mapfile reads lines safely.
mapfile -t files < <(compgen -G "$pattern" || true)
if (( ${#files[@]} == 0 )); then
echo "No files matched pattern: ${pattern}" >&2
exit 0
fi
# ---- Read password once (silent) ----
read -r -s -p "PDF password (input hidden): " PDF_PASS
echo
# ---- Helpers ----
is_encrypted() {
local f="$1"
qpdf --is-encrypted "$f" >/dev/null 2>&1
# Exit codes:
# 0 => encrypted
# 2 => not encrypted
}
orig_name_for() {
local f="$1"
if [[ "$f" == *.pdf ]]; then
printf '%s\n' "${f%.pdf}.orig.pdf"
else
printf '%s\n' "${f}.orig.pdf"
fi
}
# ---- Main loop ----
for f in "${files[@]}"; do
[[ -f "$f" ]] || continue
[[ "$f" == *.orig.pdf ]] && continue
if is_encrypted "$f"; then
tmp="${f}.tmp.$$"
orig="$(orig_name_for "$f")"
# Attempt decryption; on failure, keep the original untouched.
if qpdf --password="$PDF_PASS" --decrypt "$f" "$tmp" >/dev/null 2>&1; then
# Preserve the original; never overwrite an existing backup.
if [[ -e "$orig" ]]; then
echo "ERROR: Backup already exists, refusing to overwrite: $orig" >&2
rm -f -- "$tmp"
continue
fi
mv -- "$f" "$orig"
mv -- "$tmp" "$f"
echo "DECRYPTED: $f (backup: $orig)"
else
echo "ERROR: Failed to decrypt (wrong password or unsupported encryption): $f" >&2
rm -f -- "$tmp"
continue
fi
else
echo "SKIP (not encrypted): $f"
fi
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment