Skip to content

Instantly share code, notes, and snippets.

@albinoloverats
Created August 17, 2018 17:45
Show Gist options
  • Save albinoloverats/f7cc7ee223458790c0abbe4bdf52fd66 to your computer and use it in GitHub Desktop.
Save albinoloverats/f7cc7ee223458790c0abbe4bdf52fd66 to your computer and use it in GitHub Desktop.
compress a file/directory using the best available algorithm/application (add/delete as applicable)
#!/bin/sh
FORMATS="xz lzip lzma bzip2 gzip lzop 7z rar zip"
LEVELS=$(seq 1 9)
if test -z "$1"
then
echo "Usage: $(basename $0) <file/dir to compress> [format]"
echo "Supported formats: $FORMATS"
exit 1
fi
function format_to_ext()
{
frmt=$1
case $frmt in
"bzip2") echo "bz2" ;;
"gzip") echo "gz" ;;
"lzop") echo "lzo" ;;
"lzip") echo "lz" ;;
*) echo "$frmt" ;;
esac
}
function compress_file()
{
file=$1
xtra=$2
frmt=$3
levl=$4
extn=$(format_to_ext $frmt)
arch=$ctmp$xtra-$levl.$extn
test $frmt = "rar" -a $levl -gt 5 && return
case $frmt in
"7z") $frmt a -mx=$levl $arch $xtra >/dev/null 2>&1 ;;
"rar") $frmt a -m$levl -idq $arch $xtra ;;
"zip") $frmt -r -$levl --quiet $arch $xtra ;;
*)
arch=$ctmp$file-$levl.$extn
$frmt --stdout -$levl $file > $arch
;;
esac
echo "$(stat $arch | grep Size | awk '{print $2}') $frmt $levl $arch"
}
function remove_larger()
{
best=$1
file=$(echo $2 | cut -d" " -f4)
test $best != $file && unlink $file
}
function file_size()
{
file=$1
echo $(stat $file | grep Size | awk '{print $2}')
}
function compress_file_loop()
{
ctmp="$(mktemp --directory)/"
file=$1
xtra=$2
frmt=$3
test -z "$frmt" && frmt=$FORMATS
cpus=$(nproc)
export ctmp
export -f format_to_ext
export -f compress_file
export -f remove_larger
list=$(parallel --bar --jobs $cpus compress_file $file $xtra {} {} ::: $frmt ::: $LEVELS)
best=$(echo "$(echo "$list")" | sort | head -n1)
size=$(echo $best | cut -d" " -f1)
frmt=$(echo $best | cut -d" " -f2)
levl=$(echo $best | cut -d" " -f3)
name=$(echo $best | cut -d" " -f4)
extn=$(format_to_ext $frmt)
if test $(file_size $name) -gt $(file_size $file)
then
echo "Best left uncompressed"
name="x"
fi
parallel --jobs $cpus remove_larger $name {} ::: "$list"
arch=$file
case $frmt in
"7z") arch=$xtra ;;
"rar") arch=$xtra ;;
"zip") arch=$xtra ;;
*) ;;
esac
test $name != "x" && mv $name $arch.$extn
rmdir $ctmp
}
function compress_directory()
{
dir=$1
fmt=$2
tar --create --file $dir.tar $dir
compress_file_loop $dir.tar $dir $fmt
unlink $dir.tar
}
if test -n "$2"
then
found=0
for f in $FORMATS
do
test $f = $2 && found=1
done
if test $found -eq 0
then
echo "Unsupported archive format"
exit 1
fi
fi
if test -d $1
then
compress_directory $1 $2
elif test -f $1
then
compress_file_loop $1 $1 $2
else
echo "Unsupported file type"
exit 1
fi
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment