Архивирование и хранение. Часть 3/4. Всем привет, с вами снова TagdTagd.
На мой взгляд лучшим аналогом winrar на Linux является 7zip. И жмет качественно и быстро и удобный GUI для пользователей. И мультиплатформенный. Есть, правда, и недостатки:
- Не сохраняет права (решается предварительным созданием tar)
- Ну, напрочь отсутствуют средства восстановления. Если вдруг архив разбился - восстановить из него что-то получится едва ли.
Но это как раз проистекает из философии nix. Каждая программа должна выполнять одну функцию, но делать это хорошо. 7zip жмет очень качественно. А остальное исправим.
Итак, многие знают, что если к 7z архиву приписать другой файл «в хвост», то архив не перестанет быть архивом. Просто при тестировании и распаковке появится замечание: «WARNINGS: There are data after the end of archive».
Вот этим и воспользуемся. Берем архив, создаем par2 файл, и с помощью (cat file.7z file.par2 > file.7zpar2) сливаем в новый формат.
Достоинства этого метода:
- Архив полностью сохраняет функциональность. Его можно прям без разделения взять и разархивировать.
- Он содержит информацию для восстановления, которой можно воспользоваться.
К небольшим недостаткам данного метода можно отнести:
- par2 запоминает имена файлов в момент создания par2-файла. То есть если par2 был создан для file.7z, а потом вы его объединили и переименовали в file77.7zpar2, то восстановится файл file.7z. Но мне кажется это не существенно, по сравнению с потерей данных.
- Для восстановления потребуется объем места,
(size file.7zpar2)*2 - Максимальный размер защищаемого файла <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








Комментарии