This repository has been archived on 2024-03-04. You can view files and clone it, but cannot push or open issues or pull requests.
linux/.linux/bash/module/archive.sh

231 lines
5.8 KiB
Bash

# archive file with maximum compression and checksum.
# usage: archive [FILES]
archive()
{
local targets=("${@}") # target file(s).
local count=0 # processed count.
local total=${#} # total to process.
# set dafult value to target all supported archives.
if [[ "${targets}" = "" ]]; then
targets=(*)
total=${#targets[@]}
fi
# iterate each target.
for target in "${targets[@]}"; do
# increment counter.
((count++))
# status info.
local status="[${count}/${total}] ${target}"
echo "${status}"
# create archive.
tar -c "${target}" | pv -s $(du -sb "${target}" | awk '{print $1}') | xz -9e > "${target%/*}".tar.xz
# append hash to target name.
mv "${target%/*}".tar.xz "${target%/*}"_$(sha1sum "${target%/*}".tar.xz | cut -d\ -f1).tar.xz
done
}
# archive file with minimal compression and checksum.
# usage: archive_fast [FILES]
archive_fast()
{
local targets=("${@}") # target file(s).
local count=0 # processed count.
local total=${#} # total to process.
# set dafult value to target all supported archives.
if [[ "${targets}" = "" ]]; then
targets=(*)
total=${#targets[@]}
fi
# iterate each target.
for target in "${targets[@]}"; do
# increment counter.
((count++))
# status info.
local status="[${count}/${total}] ${target}"
echo "${status}"
# create archive.
tar -c "${target}" | pv -s $(du -sb "${target}" | awk '{print $1}') | gzip -1 > "${target%/*}".tar.gz
# append hash to target name.
mv "${target%/*}".tar.gz "${target%/*}"_$(sha1sum "${target%/*}".tar.gz | cut -d\ -f1).tar.gz
done
}
# check archive hashes.
# usage: archive_check [FILES]
archive_check()
{
local targets=("${@}") # target file(s).
local total=${#} # total to process.
local count=0 # processed count.
local failed=0 # total failed checks.
# set dafult value to target all supported archives.
if [[ "${targets}" = "" ]]; then
targets=(*_*.tar.*)
total=${#targets[@]}
fi
# iterate each target.
for target in "${targets[@]}"; do
# process only files.
[[ -f "${target}" ]] || continue
# increment counter.
((count++))
# status info.
local status="[${count}/${total}] ${target}"
# extract hash from name.
local saved="${target##*_}"
saved="${saved%%.*}"
# calculate actual hash.
local actual=$(pv "${target}" | sha1sum | cut -d\ -f1)
# compare hashes, show error on mismatch.
if [[ "${actual}" = "${saved}" ]]; then
echo "${status}: OK."
else
echo -e "${color_red}${status}: failed.${color_default}"
((failed++))
fi
done
# report result.
if [[ ${count} -gt 1 ]]; then
if [[ ${failed} -gt 0 ]]; then
echo -e "${color_bred}Items failed to validate: ${failed}.${color_default}"
else
echo -e "${color_green}All successful.${color_default}"
fi
fi
}
# extract previously created archive with checksum validation.
# usage: unarchive [FILES]
unarchive()
{
local targets=("${@}") # target file(s).
local count=0 # processed count.
local total=${#} # total to process.
# set dafult value to target all supported archives.
if [[ "${targets}" = "" ]]; then
targets=(*_*.tar.*)
total=${#targets[@]}
fi
# iterate each target.
for target in "${targets[@]}"; do
# increment counter.
((count++))
# status info.
local status="[${count}/${total}] ${target}"
# extract hash from name.
local saved="${target##*_}"
saved="${saved%%.*}"
# calculate actual hash.
local actual=$(sha1sum "${target}" | cut -d\ -f1)
# extract if hash matched or show error if not.
if [[ "${saved}" = "${actual}" ]]; then
echo "${status}: OK."
tar -xf "${target}"
else
echo "${status}: failed."
fi
done
}
# rename archive. if no name specified, it simplifies archive's name.
# usage: archive_name [ARCHIVE] [NAME]
archive_name()
{
local targets="${1}" # target archive(s).
local name="${2}" # new name.
local total=1 # total targets to process.
local count=0 # processed targets counter.
# set dafult value to target all supported archives.
if [[ "${targets}" = "" ]]; then
targets=(*_*.tar.*)
total=${#targets[@]}
fi
# iterate each target.
for target in "${targets[@]}"; do
# only work with targets.
[[ -f "${target}" ]] || continue
# iterate counter.
((count++))
# simplify name by default.
if [[ "${name}" = "" || ${count} -gt 1 ]]; then
name="${target%_*}"
name="$(parse_alnum ${name})"
fi
# remove old name.
local data="${target##*_}"
local new_name="${name}_${data}"
# prepare status.
local status="[${count}/${total}] ${target} -> ${new_name}"
# check for the same name.
if [[ "${target}" = "${new_name}" ]]; then
echo -e "${color_green}${status}: no change.${color_default}"
continue
fi
# check for existing target.
if [[ -f "${new_name}" ]]; then
echo -e "${color_red}${status}: already exists.${color_default}"
return 1
fi
# rename.
mv -- "${target}" "${new_name}" && echo "${status}" || echo -e "${color_red}${status}: error.${color_default}"
done
}
# export everything, primarily for use with parallel..
export -f archive archive_fast archive_check unarchive archive_name
# autocomplete.
_archive_name()
{
COMPREPLY=()
local cur="${COMP_WORDS[COMP_CWORD]}"
local prev="${COMP_WORDS[COMP_CWORD-1]}"
local command="${COMP_WORDS[0]}"
if [[ "${prev}" = "${command}" ]]; then
COMPREPLY=( $(compgen -W "$(ls *_*.tar.*)" -- ${cur}) )
return 0
else
local name="${prev%_*}"
COMPREPLY=( $(compgen -W "${name}" -- ${cur}) )
return 0
fi
}
complete -f -X "!*_*.tar.*" archive_check unarchive
complete -F _archive_name archive_name