Initial Commit
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Script directory and backups directory setup
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
BACKUP_DIR="${SCRIPT_DIR}/backups"
|
||||
mkdir -p "${BACKUP_DIR}"
|
||||
|
||||
# Timestamp for archive name
|
||||
TIMESTAMP="$(date +"%Y%m%d_%H%M%S")"
|
||||
ZIP_FILENAME="konsole_backup_${TIMESTAMP}.zip"
|
||||
ZIP_FILEPATH="${BACKUP_DIR}/${ZIP_FILENAME}"
|
||||
|
||||
# Temporary staging directory
|
||||
TEMP_DIR="$(mktemp -d)"
|
||||
trap 'rm -rf "${TEMP_DIR}"' EXIT
|
||||
|
||||
echo "=== Starting Konsole Configuration Backup ==="
|
||||
|
||||
# Define target paths relative to HOME
|
||||
CONFIG_PATHS=(
|
||||
".config/konsolerc"
|
||||
".local/share/konsole"
|
||||
".local/share/kxmlgui5/konsole"
|
||||
".config/konsole.notifyrc"
|
||||
".config/konsolesshconfig"
|
||||
)
|
||||
|
||||
COPIED_COUNT=0
|
||||
|
||||
for rel_path in "${CONFIG_PATHS[@]}"; do
|
||||
src_path="${HOME}/${rel_path}"
|
||||
dest_path="${TEMP_DIR}/${rel_path}"
|
||||
|
||||
if [ -e "${src_path}" ]; then
|
||||
mkdir -p "$(dirname "${dest_path}")"
|
||||
cp -a "${src_path}" "${dest_path}"
|
||||
echo " [+] Staged: ~/${rel_path}"
|
||||
COPIED_COUNT=$((COPIED_COUNT + 1))
|
||||
else
|
||||
echo " [-] Skipped (not found): ~/${rel_path}"
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "${COPIED_COUNT}" -eq 0 ]; then
|
||||
echo "Error: No Konsole configuration files found to backup."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create zip file from staging area
|
||||
echo "Creating backup archive: ${ZIP_FILENAME}..."
|
||||
(
|
||||
cd "${TEMP_DIR}"
|
||||
zip -q -r "${ZIP_FILEPATH}" .
|
||||
)
|
||||
|
||||
echo "Backup successfully saved to: ${ZIP_FILEPATH}"
|
||||
|
||||
# Retention Policy: keep at most 10 recent backup zip files
|
||||
MAX_BACKUPS=10
|
||||
|
||||
mapfile -t BACKUP_FILES < <(find "${BACKUP_DIR}" -maxdepth 1 -name "konsole_backup_*.zip" | sort -r)
|
||||
|
||||
TOTAL_BACKUPS="${#BACKUP_FILES[@]}"
|
||||
if [ "${TOTAL_BACKUPS}" -gt "${MAX_BACKUPS}" ]; then
|
||||
echo "Cleaning up older backups (keeping top ${MAX_BACKUPS})..."
|
||||
for (( i=MAX_BACKUPS; i<TOTAL_BACKUPS; i++ )); do
|
||||
file_to_remove="${BACKUP_FILES[$i]}"
|
||||
echo " Deleting old backup: $(basename "${file_to_remove}")"
|
||||
rm -f "${file_to_remove}"
|
||||
done
|
||||
fi
|
||||
|
||||
echo "=== Backup Complete (${TOTAL_BACKUPS} backup(s) currently stored) ==="
|
||||
Binary file not shown.
Executable
+142
@@ -0,0 +1,142 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
BACKUP_DIR="${SCRIPT_DIR}/backups"
|
||||
|
||||
show_diff() {
|
||||
local source_dir="$1"
|
||||
echo ""
|
||||
echo "==================== Changes Preview (Diff) ===================="
|
||||
local changes_found=0
|
||||
|
||||
while IFS= read -r -d '' item; do
|
||||
rel_path="${item#"${source_dir}"/}"
|
||||
dest_item="${HOME}/${rel_path}"
|
||||
|
||||
if [ -d "${item}" ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ ! -e "${dest_item}" ]; then
|
||||
changes_found=1
|
||||
echo -e "\n\033[1;32m[NEW FILE]\033[0m ~/${rel_path}"
|
||||
else
|
||||
if ! cmp -s "${item}" "${dest_item}"; then
|
||||
changes_found=1
|
||||
echo -e "\n\033[1;33m[MODIFIED]\033[0m ~/${rel_path}"
|
||||
if command -v git &>/dev/null; then
|
||||
git diff --no-index --color "${dest_item}" "${item}" || true
|
||||
else
|
||||
diff -u --color=always "${dest_item}" "${item}" || true
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done < <(find "${source_dir}" -type f -print0)
|
||||
|
||||
if [ "${changes_found}" -eq 0 ]; then
|
||||
echo -e "\n\033[1;32mNo differences detected. Current configuration matches the backup exactly.\033[0m"
|
||||
fi
|
||||
echo "================================================================"
|
||||
echo ""
|
||||
}
|
||||
|
||||
ARCHIVE_PATH=""
|
||||
|
||||
# 1. Check positional argument
|
||||
if [ $# -ge 1 ] && [ -n "$1" ]; then
|
||||
ARCHIVE_PATH="$1"
|
||||
# 2. Check if piped via stdin
|
||||
elif [ ! -t 0 ]; then
|
||||
read -r ARCHIVE_PATH || true
|
||||
fi
|
||||
|
||||
# 3. Interactive prompt / selection menu if no input given
|
||||
if [ -z "${ARCHIVE_PATH}" ]; then
|
||||
if [ ! -d "${BACKUP_DIR}" ]; then
|
||||
echo "Error: No backups directory found at ${BACKUP_DIR}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mapfile -t AVAILABLE_BACKUPS < <(find "${BACKUP_DIR}" -maxdepth 1 -name "konsole_backup_*.zip" | sort -r)
|
||||
|
||||
if [ "${#AVAILABLE_BACKUPS[@]}" -eq 0 ]; then
|
||||
echo "Error: No backup archives found in ${BACKUP_DIR}."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Available Konsole backups:"
|
||||
for i in "${!AVAILABLE_BACKUPS[@]}"; do
|
||||
echo " [$((i + 1))] $(basename "${AVAILABLE_BACKUPS[$i]}")"
|
||||
done
|
||||
echo " [q] Quit"
|
||||
|
||||
read -r -p "Select a backup to restore [1-${#AVAILABLE_BACKUPS[@]}]: " choice < /dev/tty
|
||||
if [[ "${choice}" =~ ^[0-9]+$ ]] && [ "${choice}" -ge 1 ] && [ "${choice}" -le "${#AVAILABLE_BACKUPS[@]}" ]; then
|
||||
ARCHIVE_PATH="${AVAILABLE_BACKUPS[$((choice - 1))]}"
|
||||
else
|
||||
echo "Aborted."
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# Expand relative paths
|
||||
if [[ "${ARCHIVE_PATH}" != /* ]]; then
|
||||
if [ -f "${BACKUP_DIR}/${ARCHIVE_PATH}" ]; then
|
||||
ARCHIVE_PATH="${BACKUP_DIR}/${ARCHIVE_PATH}"
|
||||
elif [ -f "./${ARCHIVE_PATH}" ]; then
|
||||
ARCHIVE_PATH="$(pwd)/${ARCHIVE_PATH}"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -f "${ARCHIVE_PATH}" ]; then
|
||||
echo "Error: Backup file not found: ${ARCHIVE_PATH}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Selected backup archive: ${ARCHIVE_PATH}"
|
||||
|
||||
# Extract to temporary staging directory
|
||||
TEMP_DIR="$(mktemp -d)"
|
||||
trap 'rm -rf "${TEMP_DIR}"' EXIT
|
||||
|
||||
unzip -q -o "${ARCHIVE_PATH}" -d "${TEMP_DIR}"
|
||||
|
||||
# Interactive confirmation loop (allows viewing diffs)
|
||||
while true; do
|
||||
echo ""
|
||||
echo "Konsole configuration files to be restored:"
|
||||
find "${TEMP_DIR}" -mindepth 1 -maxdepth 3 | while read -r f; do
|
||||
rel="${f#"${TEMP_DIR}"/}"
|
||||
echo " - ~/${rel}"
|
||||
done
|
||||
echo ""
|
||||
|
||||
if [ -t 0 ]; then
|
||||
INPUT_SRC="/dev/stdin"
|
||||
else
|
||||
INPUT_SRC="/dev/tty"
|
||||
fi
|
||||
|
||||
read -r -p "Choose action: [r] Restore / [d] View Diff / [c] Cancel: " action < "${INPUT_SRC}"
|
||||
|
||||
case "${action,,}" in
|
||||
r|y|yes)
|
||||
echo "Restoring configuration files..."
|
||||
cp -a "${TEMP_DIR}/." "${HOME}/"
|
||||
echo -e "\033[1;32mKonsole configurations restored successfully from $(basename "${ARCHIVE_PATH}")!\033[0m"
|
||||
echo "Note: If Konsole is currently running, please restart it to apply all settings."
|
||||
break
|
||||
;;
|
||||
d|diff)
|
||||
show_diff "${TEMP_DIR}"
|
||||
;;
|
||||
c|q|n|no|cancel)
|
||||
echo "Restoration cancelled."
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Invalid option. Please enter 'r', 'd', or 'c'."
|
||||
;;
|
||||
esac
|
||||
done
|
||||
Reference in New Issue
Block a user