Created
November 11, 2025 22:31
-
-
Save Urpagin/229726e00e693a596ce19d5123d52844 to your computer and use it in GitHub Desktop.
Archives a directory simply and efficiently (but slowly mx=9). (output is .tar.7z)
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 | |
| # Author: Urpagin | |
| # Date: 2025-11-11 around 20:00. | |
| # License: MIT | |
| # Description: - Makes a backup of an entire directory (including hidden files) | |
| # and conserving permissions and other metadata using the tar algo first. | |
| # - Creates .tar.7z files and uses maximum 7z compression. | |
| # - CLI flags for a filename, appends the date after. | |
| # E.g., <name>_YYYY-MM-DD_HH-MM-SS.tar.7z | |
| # Flaws: No functions + I'm not great heh + surely ridden with unthought edges cases. | |
| set -euo pipefail | |
| usage() { | |
| cat << EOF | |
| USAGE: | |
| $0 -d <directory to backup> -n <name of the archive> [-y] | |
| DESCRIPTION: | |
| Makes a .tar.7z maximally compressed backup of the input directory. | |
| Saves it as <name>_YYYY-MM-DD_HH-MM-SS.tar.7z in the current directory. | |
| -y does not prompt the user for confirmation. | |
| EOF | |
| exit 1 | |
| } | |
| # The dir to backup. | |
| _target_dir='' | |
| # The dir where to save the archive. | |
| _archive_dir="$(pwd)" | |
| # The name of the archive. | |
| _archive_suffix='' | |
| _y_arg='false' | |
| _REQUIRED_COMMANDS=( getopts tar 7z ) | |
| for cmd in "${_REQUIRED_COMMANDS[@]}"; do | |
| if ! command -v "$cmd" >/dev/null 2>&1; then | |
| echo "Command $cmd is required." >&2 | |
| exit 1 | |
| fi | |
| done | |
| while getopts ":d:n:y" opt; do | |
| case "$opt" in | |
| d) | |
| _target_dir="$OPTARG" | |
| ;; | |
| n) | |
| _archive_suffix="$OPTARG" | |
| ;; | |
| y) | |
| _y_arg=true | |
| ;; | |
| \?) | |
| echo "Unknown option: -$OPTARG" >&2 | |
| usage | |
| ;; | |
| :) | |
| echo "Option -$OPTARG requires an argument." >&2 | |
| usage | |
| ;; | |
| esac | |
| done | |
| # Drop the parsed options from "" | |
| shift $((OPTIND - 1)) | |
| # Validation | |
| [[ -z "$_target_dir" ]] && { echo "Missing -d <directory>"; usage; } | |
| [[ ! -d "$_target_dir" ]] && { echo "Target directory '$_target_dir' not found."; usage; } | |
| [[ -z "$_archive_suffix" ]] && { echo "Missing -n <name of the archive>"; usage; } | |
| # E.g., test_2025-11-23.tar.7z | |
| _archive_filename="${_archive_suffix}_$(date +%F_%H-%M-%S).tar.7z" | |
| # E.g., /home/user/Documents/test_2025-11-23.tar.7z | |
| _archive_path="${_archive_dir}/${_archive_filename}" | |
| if [[ -e "$_archive_path" ]]; then | |
| echo "Archive already exists: $_archive_path" >&2 | |
| exit 1 | |
| fi | |
| _prompt_user() { | |
| echo 'Calculating size...' | |
| _target_dir_size=$(du -sh -- "$_target_dir" | cut -f 1) | |
| printf 'Backing up:\n'%s' (%s) -> '%s'\n' "$_target_dir" "$_target_dir_size" "$_archive_path" | |
| # Ask user for confirmation | |
| # https://stackoverflow.com/questions/1885525/how-do-i-prompt-a-user-for-confirmation-in-bash-script | |
| read -p "Back up? (y/N): " -n 1 -r; echo | |
| if [[ ! $REPLY =~ ^[Yy]$ ]]; then | |
| echo 'Aborted.' | |
| exit 0 | |
| fi | |
| } | |
| # No prompts if -y | |
| [[ "$_y_arg" == true ]] || _prompt_user | |
| # Create the archive | |
| tar cf - --exclude="$_archive_filename" -C "$_target_dir" . | \ | |
| 7z a -t7z -mx=9 -si"archive.tar" "$_archive_path" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment