Архивирование и хранение. Часть 3/4. Всем привет, с вами снова TagdTagd.

На мой взгляд лучшим аналогом winrar на Linux является 7zip. И жмет качественно и быстро и удобный GUI для пользователей. И мультиплатформенный. Есть, правда, и недостатки:

  1. Не сохраняет права (решается предварительным созданием tar)
  2. Ну, напрочь отсутствуют средства восстановления. Если вдруг архив разбился - восстановить из него что-то получится едва ли.

Но это как раз проистекает из философии nix. Каждая программа должна выполнять одну функцию, но делать это хорошо. 7zip жмет очень качественно. А остальное исправим.

Итак, многие знают, что если к 7z архиву приписать другой файл «в хвост», то архив не перестанет быть архивом. Просто при тестировании и распаковке появится замечание: «WARNINGS: There are data after the end of archive».

Вот этим и воспользуемся. Берем архив, создаем par2 файл, и с помощью (cat file.7z file.par2 > file.7zpar2) сливаем в новый формат.

Tagd Tagd
Tagd Tagd
Bash Master
Задать вопрос
Но это как раз проистекает из философии nix. Каждая программа должна выполнять одну функцию, но делать это хорошо. 7zip жмет очень качественно. А остальное исправим.

Достоинства этого метода:

  1. Архив полностью сохраняет функциональность. Его можно прям без разделения взять и разархивировать.
  2. Он содержит информацию для восстановления, которой можно воспользоваться.

К небольшим недостаткам данного метода можно отнести:

  1. par2 запоминает имена файлов в момент создания par2-файла. То есть если par2 был создан для file.7z, а потом вы его объединили и переименовали в file77.7zpar2, то восстановится файл file.7z. Но мне кажется это не существенно, по сравнению с потерей данных.
  2. Для восстановления потребуется объем места, (size file.7zpar2)*2
  3. Максимальный размер защищаемого файла <900Гб при RECV_PROMILE=1 (ограничения 2 Гб на par2 файл)

Собственно скрипт:

#!/bin/bash

# (c) Tagd v.2026-09-08
# merge restore information (par2) to end of file
# if no output file, recovery record added in place
# and file will be renamed
# usage: create_par2.sh /path/inputfile.7z [/path/outputfile.7zpar2]
# 

declare -i RECV_PROMILE=10 # size recovery info (must <2Gb) from input file
declare -i BLOCK_COUNT=2000 # 2 - 32764
declare -i RECV_BCOUNT=$((BLOCK_COUNT*RECV_PROMILE/1000))
declare -i RESULT=2 I=0

declare -x PATH="/usr/local/bin:/usr/bin:/bin"
(($#))|| { head -7 "$0";exit; } #help

declare INFILE_NAME="$1"
declare OUTFILE_NAME="${1}par2"
declare PARFILE_NAME="$INFILE_NAME.par2"
declare START_BLOCK="00000"
(($#==2)) && OUTFILE_NAME="$2"

[[ -f "$INFILE_NAME" ]] || { echo no file $INFILE_NAME >&2; exit 3; } #file not found
[[ -f "$OUTFILE_NAME" ]] && rm "$OUTFILE_NAME" 
  
((BLOCK_COUNT<2)) && BLOCK_COUNT=2
((BLOCK_COUNT>32764)) && BLOCK_COUNT=32764
((RECV_BCOUNT<2)) && RECV_BCOUNT=2
((RECV_BCOUNT>32764)) && RECV_BCOUNT=32764

START_BLOCK=${START_BLOCK::${#RECV_BCOUNT}}

rm "$INFILE_NAME"*.par2 2>/dev/null
par2 create -qq -n1 -b${BLOCK_COUNT} -c${RECV_BCOUNT} "$PARFILE_NAME" "$INFILE_NAME" && ((--RESULT))

# -b<n>  Set the Block‐Count
# -c<n>  Recovery block count (don't use both -r and -c)
# -n<n>  Number of recovery files (don't use both -n and -l)
# -qq silent mode

RECV_VOL="$INFILE_NAME.vol${START_BLOCK}+${RECV_BCOUNT}.par2" 
if (($#==2));then #merge
  cat "$INFILE_NAME" "$RECV_VOL" >"$OUTFILE_NAME" && ((--RESULT))
else #merge in place
  cat "$RECV_VOL" >>"$INFILE_NAME" &&
    mv "$INFILE_NAME" "$OUTFILE_NAME" && ((--RESULT))
fi  
rm "$INFILE_NAME"*.par2 2>/dev/null
exit $RESULT

chmod +x ./create_par2.sh