====== Compress Image ====== //**Входит в набор [[projects:linux:manual_backup_scripts|rPi Seal]]**// #!/bin/bash export LANG=en_US.UTF-8 export LC_ALL=en_US.UTF-8 # ==DIS/AUTOEXEC== # ===Compress image=== # 07_compress_image.sh — архивирует .img в .gz или .zst по выбору # set -euo pipefail # === Выбор формата архивации === echo "📦 Выберите формат архивации:" echo "1 - gzip (.gz) — однопоточно" echo "2 - pigz (.gz) — многопоточно (рекомендуется)" echo "3 - zstd (.zst) — встроенный прогресс без pv" echo "0 - Отмена" read -rp "👉 Ваш выбор: " fmt [[ "$fmt" == "0" || -z "$fmt" ]] && echo "❎ Отменено." && exit 0 case "$fmt" in 1) ARCHIVER="gzip" EXT="gz" ; USE_PV=true ;; 2) ARCHIVER="pigz" EXT="gz" ; USE_PV=true ;; 3) ARCHIVER="zstd" EXT="zst" ; USE_PV=false ;; *) echo "❌ Неверный выбор."; exit 1 ;; esac # === Проверка зависимостей === # Проверка основной утилиты архивации if ! command -v "$ARCHIVER" &>/dev/null; then echo "❌ Требуется утилита '$ARCHIVER'. Установить? [Y/n]" read -r ans if [[ "$ans" =~ ^[Yy]$ || -z "$ans" ]]; then sudo apt update && sudo apt install -y "$ARCHIVER" else echo "⏩ Пропуск: $ARCHIVER не установлен" exit 1 fi fi # Проверка pv только если требуется if [[ "$USE_PV" == true ]]; then if ! command -v pv &>/dev/null; then echo "❌ Требуется утилита 'pv'. Установить? [Y/n]" read -r ans if [[ "$ans" =~ ^[Yy]$ || -z "$ans" ]]; then sudo apt update && sudo apt install -y pv else echo "⏩ Пропуск: pv не установлен" exit 1 fi fi fi # --- Выбор устройства / начало блока --- NAS_PATH="/mnt/backup_nas" if mountpoint -q "$NAS_PATH"; then mapfile -t DEVICES < <(lsblk -nrpo NAME,SIZE,MOUNTPOINT | grep -E "/dev/sd|/dev/nvme" | awk '{print $1":"$2":"$3}') DEVICES+=("$NAS_PATH::NAS") else mapfile -t DEVICES < <(lsblk -nrpo NAME,SIZE,MOUNTPOINT | grep -E "/dev/sd|/dev/nvme" | awk '{print $1":"$2":"$3}') fi if [[ ${#DEVICES[@]} -eq 0 ]]; then echo "❌ Нет доступных устройств." exit 1 fi echo "💾 Выберите диск с .img-файлами:" i=1 for dev in "${DEVICES[@]}"; do IFS=":" read -r name size mnt <<< "$dev" label="" [[ "$mnt" == "NAS" ]] && label="🖧 сетевой диск" [[ -z "$mnt" && -z "$label" ]] && label="🔌 не примонтировано" echo "$i - $name $size $mnt $label" ((i++)) done echo "0 - Отмена" read -rp "👉 Ваш выбор: " choice [[ "$choice" == "0" || -z "$choice" ]] && echo "❎ Отменено." && exit 0 (( choice < 1 || choice > ${#DEVICES[@]} )) && echo "❌ Неверный выбор." && exit 1 SEL_DEV="${DEVICES[$((choice-1))]}" IFS=":" read -r DEV_NAME DEV_SIZE DEV_MNT <<< "$SEL_DEV" TEMP_MOUNTED=false if [[ "$DEV_NAME" == "$NAS_PATH" ]]; then TARGET_DIR="$NAS_PATH" echo "📁 Используем NAS каталог: $TARGET_DIR" else MOUNTED_PATH=$(lsblk -nrpo NAME,MOUNTPOINT "$DEV_NAME" | awk '$2!="" {print $2; exit}') if [[ -n "$MOUNTED_PATH" ]]; then echo "✅ Используем: $MOUNTED_PATH" TARGET_DIR="$MOUNTED_PATH" else i=0 while true; do MNT_PATH="/mnt/rpi_target$i" if ! mountpoint -q "$MNT_PATH"; then break fi ((i++)) done sudo mkdir -p "$MNT_PATH" if sudo mount "$DEV_NAME" "$MNT_PATH"; then echo "✅ Устройство примонтировано: $MNT_PATH" TARGET_DIR="$MNT_PATH" TEMP_MOUNTED=true else echo "❌ Не удалось примонтировать." exit 1 fi fi fi # --- Выбор устройства / конец блока --- # === Поиск образов === mapfile -t IMG_LIST < <(find "$TARGET_DIR" -maxdepth 1 -type f -name "*.img") if [[ ${#IMG_LIST[@]} -eq 0 ]]; then echo "❌ Не найдено .img файлов в $TARGET_DIR" $TEMP_MOUNTED && sudo umount "$TARGET_DIR" exit 1 fi echo "🗂️ Найденные образы:" i=1 for img in "${IMG_LIST[@]}"; do echo "$i - $img" ((i++)) done echo "0 - Отмена" read -rp "👉 Выберите образ для сжатия: " img_choice [[ "$img_choice" == "0" || -z "$img_choice" ]] && echo "❎ Отменено." && $TEMP_MOUNTED && sudo umount "$TARGET_DIR" && exit 0 (( img_choice < 1 || img_choice > ${#IMG_LIST[@]} )) && echo "❌ Неверный выбор." && exit 1 IMGFILE="${IMG_LIST[$((img_choice-1))]}" # === Сжатие === echo "[*] Сжимаю $IMGFILE в формат .$EXT..." OUTFILE="$IMGFILE.$EXT" if [[ -f "$OUTFILE" ]]; then read -rp "⚠️ Файл уже существует. Перезаписать? (y/N): " confirm [[ "$confirm" =~ ^[Yy]$ ]] || { echo "❎ Отмена."; $TEMP_MOUNTED && sudo umount "$TARGET_DIR"; exit 0; } rm -f "$OUTFILE" fi SIZE_ORIG=$(du -m "$IMGFILE" | cut -f1) [[ "$SIZE_ORIG" -eq 0 ]] && echo "❌ Размер файла 0 МБ. Отмена." && exit 1 if [[ "$ARCHIVER" == "zstd" ]]; then echo "ℹ️ Используется ZSTD (без pv, с встроенным прогрессом)" zstd -19 -T0 "$IMGFILE" -o "$OUTFILE" else echo "ℹ️ Используется ${ARCHIVER^^} — формат .gz" pv "$IMGFILE" | "$ARCHIVER" -9 > "$OUTFILE" fi SIZE_NEW=$(du -m "$OUTFILE" | cut -f1) SAVED=$((SIZE_ORIG - SIZE_NEW)) PERCENT=$(awk "BEGIN {printf \"%.1f\", 100*$SAVED/$SIZE_ORIG}") echo "✅ Сжатие завершено: $OUTFILE" echo "📉 Экономия: $SAVED МБ (~$PERCENT%)" $TEMP_MOUNTED && sudo umount "$TARGET_DIR" ===== ******* ===== [[https://boosty.to/takraztak/donate|Поддержать через Boosty]]