370 lines
12 KiB
Bash
370 lines
12 KiB
Bash
#!/usr/bin/env bash
|
|
# ------------------------------------------------------------------------------
|
|
# Copyright (c) 2013-2022 Geoffray Levasseur <fatalerrors@geoffray-levasseur.org>
|
|
# Protected by the BSD3 license. Please read bellow for details.
|
|
#
|
|
# * Redistribution and use in source and binary forms,
|
|
# * with or without modification, are permitted provided
|
|
# * that the following conditions are met:
|
|
# *
|
|
# * Redistributions of source code must retain the above
|
|
# * copyright notice, this list of conditions and the
|
|
# * following disclaimer.
|
|
# *
|
|
# * Redistributions in binary form must reproduce the above
|
|
# * copyright notice, this list of conditions and the following
|
|
# * disclaimer in the documentation and/or other materials
|
|
# * provided with the distribution.
|
|
# *
|
|
# * Neither the name of the copyright holder nor the names
|
|
# * of any other contributors may be used to endorse or
|
|
# * promote products derived from this software without
|
|
# * specific prior written permission.
|
|
# *
|
|
# * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
|
# * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
|
# * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
# * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
# * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
# * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
# * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
# * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
# * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
# * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
# * OF SUCH DAMAGE.
|
|
# ------------------------------------------------------------------------------
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Smartly uncompress archives (zip only for now)
|
|
# ------------------------------------------------------------------------------
|
|
utaz()
|
|
{
|
|
for opt in $@; do
|
|
case $opt in
|
|
"-h" | "--help")
|
|
echo "utaz: uncompress all the given files and/or the ones found in the given"
|
|
echo " directories creating an host directory where needed."
|
|
echo
|
|
echo "Usage: utaz [option] [directorie(s)|file(s)]"
|
|
echo
|
|
echo "Options:"
|
|
echo " -h, --help Display that help screen"
|
|
echo " -d, --delete If decompression succeeded, delete the source file"
|
|
echo " -c, --create-dir Always create a host directory"
|
|
echo " -n, --no-dir Never create a host directory"
|
|
echo
|
|
return 0
|
|
;;
|
|
|
|
"-d" | "--delete")
|
|
local willrm=1
|
|
;;
|
|
|
|
"-c" | "--create-dir")
|
|
local createdir=1
|
|
;;
|
|
|
|
"-n" | "--no-dir")
|
|
local nodir=1
|
|
;;
|
|
|
|
"-"*)
|
|
disp E "Invalid option, use \"utaz --help\" to display options list"
|
|
echo
|
|
return 1
|
|
;;
|
|
|
|
*)
|
|
# The ${opt%/} writing is to remove trailing / if any
|
|
local LIST="$LIST ${opt%/}"
|
|
;;
|
|
esac
|
|
done
|
|
|
|
[[ $createdir && $nodir ]] && \
|
|
disp E "The --create-dir and --no-dir options are mutually exclusive."
|
|
|
|
[[ ! $LIST ]] && local LIST="."
|
|
|
|
for zitem in $LIST; do
|
|
shopt -s nullglob
|
|
local zips=("$zitem"/*.zip)
|
|
shopt -u nullglob
|
|
[[ ${#zips[@]} -eq 0 ]] && \
|
|
disp W "$zitem contains no supported archive file, skipping." && \
|
|
continue
|
|
|
|
for f in "$zitem"/*.zip; do
|
|
disp I "Processing archive $f... "
|
|
local dir=${f::-4}
|
|
|
|
mkdir -p "$dir"
|
|
[[ $? -gt 0 ]] &&
|
|
disp E "The filesystem can't create directories, exit!" &&
|
|
return 1
|
|
|
|
unzip -o "$f" -d "$dir" >/dev/null 2>&1
|
|
case $? in
|
|
0)
|
|
[[ $willrm ]] && rm -f "$f" && disp I "File $zitem/$f deleted."
|
|
;;
|
|
|
|
1)
|
|
disp W "Compression program returned a warning: deletion canceled."
|
|
;;
|
|
*)
|
|
disp E "The zip file seems corrupted, failed."
|
|
rm -rf "$dir" >/dev/null 2>&1
|
|
continue
|
|
;;
|
|
esac
|
|
|
|
if [[ $createdir ]]; then
|
|
disp I "Archive extracted successfully in subdirectory."
|
|
elif [[ $nodir ]]; then
|
|
mv "./$dir/"* ./ && rmdir "$dir"
|
|
disp I "Archive extracted successfully, no subdirectory needed."
|
|
else
|
|
subdirs=$(find $dir -maxdepth 1 | wc -l)
|
|
if [[ $subdirs -eq 2 ]]; then
|
|
mv ./$dir/* ./ && rmdir $dir
|
|
disp I "Archive extracted successfully, no subdirectory needed."
|
|
else
|
|
disp I "Archive extracted successfully in subdirectory."
|
|
fi
|
|
fi
|
|
done
|
|
done
|
|
}
|
|
export -f utaz
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Compress directories or files into one or more archive
|
|
# ------------------------------------------------------------------------------
|
|
taz()
|
|
{
|
|
_doxz()
|
|
{
|
|
command -v xz >/dev/null 2>&1 || {
|
|
disp E "The program 'xz' is not installed, aborting."
|
|
return 127
|
|
}
|
|
|
|
[[ $4 ]] && local verb='-v'
|
|
|
|
# Display a warning for this format
|
|
disp W "xz format is not suited for long term archiving."
|
|
disp I "See https://www.nongnu.org/lzip/xz_inadequate.html for details."
|
|
|
|
# Compresse to xz (lzma2) - Deprecated
|
|
xz $verb --compress --keep -$3 -T $2 $1
|
|
return $?
|
|
}
|
|
|
|
_dolz()
|
|
{
|
|
local procopt="--threads $2"
|
|
local command=plzip
|
|
|
|
command -v plzip >/dev/null 2>&1 || {
|
|
command -v lzip >/dev/null 2>&1 || {
|
|
disp E "Program 'plzip' or 'lzip' are not installed, aborting."
|
|
return 127
|
|
}
|
|
command=lzip
|
|
local procopt=""
|
|
[[ $2 -gt 1 ]] &&
|
|
disp W "lzip doesn't support multithreading, falling back to 1 thread." &&
|
|
disp W "Consider installing plzip to obtain multithreading abilities."
|
|
}
|
|
|
|
[[ $4 ]] && local verb="-vv"
|
|
|
|
# Compresse au format lzip (lzma)
|
|
$command $verb $procopt --keep -$3 $1
|
|
return $?
|
|
}
|
|
|
|
_dogz()
|
|
{
|
|
local procopt="--processes $2"
|
|
local command=pigz
|
|
|
|
command -v pigz >/dev/null 2>&1 || {
|
|
command -v gzip >/dev/null 2>&1 || {
|
|
disp E "Programs 'pigz' or 'gzip' are not installed, aborting."
|
|
return 127
|
|
}
|
|
local command="gzip --compress"
|
|
local procopt=""
|
|
[[ $2 -gt 1 ]] &&
|
|
disp W "gzip doesn't support multithreading, falling back to 1 thread." &&
|
|
disp W "Consider installing pigz to obtain multithreading abilities."
|
|
}
|
|
|
|
[[ $4 ]] && local verb="--verbose"
|
|
|
|
# Compresse au format bz2
|
|
$command $verb $procopt --keep -$3 $1
|
|
return $?
|
|
}
|
|
|
|
_dobz2()
|
|
{
|
|
local procopt="-p$2"
|
|
local command=pbzip2
|
|
|
|
command -v pbzip2 >/dev/null 2>&1 || {
|
|
command -v bzip2 >/dev/null 2>&1 || {
|
|
disp E "The program 'pbzip2' or 'bzip2' are not installed, aborting."
|
|
return 127
|
|
}
|
|
local command=bzip2
|
|
local procopt=""
|
|
[[ $2 -gt 1 ]] &&
|
|
disp W "bzip2 doesn't support multithreading, falling back to 1 thread." &&
|
|
disp W "Consider installing pbzip2 to obtain multithreading abilities."
|
|
}
|
|
|
|
[[ $4 ]] && local verb="-v"
|
|
|
|
# Compresse au format bz2
|
|
$command $verb --compress $procopt --keep -$3 $1
|
|
return $?
|
|
}
|
|
|
|
_dolzo()
|
|
{
|
|
command -v lzop >/dev/null 2>&1 || {
|
|
disp E "The program 'lzop' is not installed, aborting."
|
|
return 127
|
|
}
|
|
|
|
[[ $4 ]] && local verb='-v'
|
|
[[ $2 -gt 1 ]] && disp W "lzop doesn't support multithreading, falling back to 1 thread."
|
|
|
|
# Compresse au format lzo
|
|
lzop --keep -$3 $1
|
|
return $?
|
|
}
|
|
|
|
for opt in $@; do
|
|
case $opt in
|
|
"-h" | "--help")
|
|
echo "taz: archive all files of a directory."
|
|
echo
|
|
echo "Usage: taz [option] [--parallel=<n>] [--format=<format>] [directory1 ... directoryN]"
|
|
echo
|
|
echo "Options:"
|
|
echo " -h, --help Display that help screen"
|
|
echo " -d, --delete Delete source file or directory after success"
|
|
echo " -f, --format Chose archive format in the given list. If several format are"
|
|
echo " given, the smalest is kept"
|
|
echo " -p, --parallel Number of threads to use (if allowed by underlying utility)"
|
|
echo " -v, --verbose Display progress where possible"
|
|
echo " -q, --quiet Display less messages (only errors and warnings)"
|
|
echo " -1, .., -9 Compression level to use [1=fast/biggest, 9=slow/smallest]"
|
|
echo
|
|
echo "Supported archive format:"
|
|
echo " Param.| programs | Algo. | Description"
|
|
echo " ------+---------------+-------+----------------------------------------"
|
|
echo " lz | plzip, lzip | lzma | Safe efficient default format"
|
|
echo " xz | xz | lzma2 | Unsafe, not for long term"
|
|
echo " bz2 | pbzip2, bzip2 | bzip2 | Historical but less efficient than lz"
|
|
echo " gz | pigz, gzip | lz77 | Historical, safe, fast"
|
|
echo " lzo | lzop | lzo | Very fast but no multithread"
|
|
echo " tar | tar | tar | No compression"
|
|
echo
|
|
return 0
|
|
;;
|
|
|
|
"-d" | "--delete")
|
|
local willrm=1
|
|
;;
|
|
|
|
"-f"?* | "--format"?*)
|
|
local compform=$(echo "$opt" | cut -f 2- -d '=')
|
|
;;
|
|
|
|
"-p"?* | "--parallel"?*)
|
|
local nproc=$(echo "$opt" | cut -f 2- -d '=')
|
|
;;
|
|
|
|
"-v" | "--verbose")
|
|
local verbose=1
|
|
;;
|
|
|
|
"-q" | "--quiet")
|
|
local quiet=1
|
|
;;
|
|
|
|
"-"*)
|
|
local complevel=$(echo $opt | sed 's/-//')
|
|
if ! [[ $complevel =~ ^[1-9]+$ ]]; then
|
|
disp E "Invalid option, use taz --help to display options list"
|
|
echo
|
|
return 1
|
|
fi
|
|
;;
|
|
|
|
*)
|
|
local LIST="$LIST ${opt%/}"
|
|
;;
|
|
esac
|
|
done
|
|
|
|
[[ ! $compform ]] && compform=lz # safe and efficient (unless data are already compressed)
|
|
[[ ! $nproc ]] && nproc=1
|
|
[[ ! $complevel ]] && complevel=6
|
|
[[ $verbose -gt 1 && $quiet -gt 1 ]] &&
|
|
disp E "The --verbose and --quiet options can't be used together."
|
|
|
|
for item in $LIST; do
|
|
local donetar=0
|
|
disp I "Processing $item..."
|
|
|
|
if [[ -d "$item" ]]; then
|
|
disp I "\t Creating $item.tar... "
|
|
|
|
tar -cf "$item.tar" "$item"
|
|
if [[ ! $? -eq 0 ]]; then
|
|
disp E "tar file creation failed, skipping to next item."
|
|
continue
|
|
fi
|
|
|
|
local donetar=1
|
|
fi
|
|
|
|
local fname=$item
|
|
[[ $donetar -gt 0 ]] && fname=$item.tar
|
|
|
|
# Skip compression part if tar is asked
|
|
if [[ $compform != "tar" ]]; then
|
|
disp I "\t Compressing archive..."
|
|
_do$compform "$fname" "$nproc" "$complevel" "$verbose"
|
|
[[ ! $? -eq 0 ]] && case $? in
|
|
127)
|
|
disp E "Compression program unavailable, aborting."
|
|
return 127
|
|
;;
|
|
*)
|
|
disp E "Compression program returned an error, not deleting anything if asked, skipping to next item."
|
|
continue
|
|
;;
|
|
esac
|
|
|
|
[[ $donetar -gt 0 ]] && rm "$fname"
|
|
fi
|
|
|
|
if [[ $willrm ]]; then
|
|
disp I "\t Deleting original source as asked... "
|
|
rm -r "$item"
|
|
fi
|
|
done
|
|
unset quiet
|
|
}
|
|
export -f taz
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# EOF
|