Advertisement
pintcat

make-7z - simple frontend for 7-Zip

Apr 24th, 2025 (edited)
157
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 3.84 KB | Software | 0 0
  1. #!/bin/sh
  2. # make-7z v1.16 - frontend for 7-Zip with a nice progress bar. Usage: make-7z.sh [path to source file or dir] [path to target file]
  3. # Source path must lead to a file or directory. If no target is given the source path and name is used for the archive.
  4. # The 7z suffix will be added automatically if not present in the target file name. The following variables can be used to override
  5. # the default settings: $PS for compression preset (0-9; default: 9), $DS for dictionary size (up to 3840; determined automatically
  6. # by default), $FB for fast bytes aka word size (up to 273; default: 273), $MT number of CPU threads (default: 3).
  7.  
  8. ERROR(){ # Print error message & exit with return code 1.
  9.     printf "\033[0;31mError - $1\033[0;32m"
  10.     exit 1
  11. }
  12.  
  13. # Check dependencies: progress.sh, 7z (progress.sh is no longer mandatory & ignored if not present)
  14. touch ${LOG=/media/ramdisk/log_$(date +%y%m%d%H%M%S%3N)}
  15. PROGRESS=$(type progress.sh) && PROGRESS="/"${PROGRESS##* /}
  16. [ -f "$PROGRESS" ] || PROGRESS=$LOG
  17. SZIP=$(type 7z) && SZIP="/"${SZIP##* /}
  18. [ -x "$SZIP" ] || ERROR "7z is either missing or not executable\n"
  19.  
  20. . "$PROGRESS"
  21.  
  22. PROGRESS_R1=" "
  23. PROGRESS_FT=T
  24. PROGRESS_MSG=" Compressed file size compared to original: "
  25.  
  26. # Check source & target path & file name
  27. [ -z "$1" ] || [ ! -e "$1" ] && ERROR "Wrong input path or file name or none at all.\n"
  28. if [ -z "$2" ]; then
  29.     OUT=$(printf "$1" | sed 's:/*$::').7z    # remove all trailing slashes & add suffix
  30. else
  31.     FILENAME=${2%*.7z}
  32.     [ -z ${2#$FILENAME*} ] && OUT="$2".7z || OUT="$2"
  33. fi
  34. if [ -e "$OUT" ]; then
  35.     read -r -p "Output file already exists. Overwrite (y/N)? " OPT
  36.     case $OPT in
  37.         y|Y)
  38.             rm -f "$OUT";;
  39.         *)
  40.             ERROR "Unable to write output file.\n";;
  41.     esac
  42. fi
  43.  
  44. # Calculate optimal dictionary size according to available RAM & the amount of data to compress
  45. DICT=64
  46. DSTEP=$(($DICT/2))
  47. [ $((PROGRESS_MAX2=$(du -s "$1" | cut -f1))) -lt 3932160 ] && DMAX=$((($PROGRESS_MAX2+511)/1024)) || DMAX=3840
  48. while [ $(((($DICT+$DSTEP)*1088+56)/100)) -le $(($(awk '/lable:/ {printf $2}' /proc/meminfo)/1024)) ] && [ $DICT -lt $DMAX ]; do
  49.     [ $((DICT=$DICT+$DSTEP)) -gt 3840 ] && DICT=3840
  50.     [ $(($DSTEP*4)) -eq $DICT ] && DSTEP=$(($DSTEP*2))
  51. done
  52.  
  53. # Check cpression settings (can be set manually by exporting the corresponding variables)
  54. [ -z $PS ] || [ -z "${PS##*[!0-9]*}" ] || [ $PS -gt 9 ] && PS=9
  55. [ -z $DS ] || [ -z "${DS##*[!0-9]*}" ] || [ $DS -gt $DICT ] && DS=$DICT
  56. [ -z $FB ] || [ -z "${FB##*[!0-9]*}" ] || [ $FB -gt 273 ] && FB=273
  57. CCORES=$(grep -m1 "siblings" /proc/cpuinfo | cut -d" " -f2)
  58. if [ -n "$MT" ] && [ -n "${MT##*[!0-9]*}" ] && [ $MT -gt 0 ]; then
  59.     [ $MT -gt $CCORES ] && MT=$CCORES
  60. else
  61.     [ $CCORES -gt 3 ] && MT=3 || MT=$CCORES
  62. fi
  63. COMPRESS="-mx=$PS -md="$DS"m -mfb=$FB -mmt=$MT"
  64.  
  65. # Start compression
  66. if [ -z "$(command -V PROGRESS_BAR | grep function)" ]; then
  67.     $SZIP a "$OUT" "$1" $COMPRESS -snl
  68. else
  69.     exec $SZIP a "$OUT" "$1" $COMPRESS -snl -bso1 -bsp1 >$LOG &
  70.     while [ -z "$(grep 7-Zip $LOG)" ]; do # wait for 7-Zip to open its log
  71.         sleep 0.2s
  72.     done
  73.     tail -n +2 $LOG
  74.     printf "\033[\rAPreset: $PS, dictionary size: "$DS"mb, word size: $FB, number of CPU threads: $MT\n"
  75.     while [ -n "$(ps -e | grep ' 7z')" ]; do
  76.         sleep 0.1s
  77.         PROG=$(tr -d '\b\n' <$LOG | awk -F'% \\+ |% [0-9]+ \\+ ' '{print $(NF-1)}' | awk -F" " '{printf $NF}')
  78.         if [ -n "${PROG##*[!0-9]*}" ]; then
  79.             [ $PROG -eq 0 ] && DIV=1 || DIV=$PROG
  80.             RATIO=$((($(du -s "$OUT" | cut -f1)*100+$DIV*10/18)/$DIV))
  81.             if [ $((COUNT=$COUNT+1)) -le 5 ]; then
  82.                 RATIO_AVG=$(($RATIO_AVG+$RATIO))
  83.                 PROGRESS_BAR $PROG $(($RATIO_RES+0))
  84.             else
  85.                 RATIO_RES=$((($RATIO_AVG*10+28)/50))
  86.                 [ $RATIO_RES -gt $PROGRESS_MAX2 ] && RATIO_AVG=$PROGRESS_MAX
  87.                 COUNT=1
  88.                 RATIO_AVG=$RATIO_RES
  89.                 PROGRESS_BAR $PROG $RATIO_RES
  90.             fi
  91.         fi
  92.     done
  93.     PROGRESS_BAR 100 $(du -s "$OUT" | cut -f1)
  94.     printf "\033[4B\n"
  95. fi
  96. rm -f $LOG
  97.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement