From 49794165f838e6527ab5c07901ff57465fbe6549 Mon Sep 17 00:00:00 2001 From: home Date: Sat, 16 Dec 2023 22:52:36 +0300 Subject: [PATCH] archive : utilize _iterate_target. --- .config/bash/module/archive.sh | 339 +++++++-------------------------- .config/bash/module/util.sh | 6 +- 2 files changed, 67 insertions(+), 278 deletions(-) diff --git a/.config/bash/module/archive.sh b/.config/bash/module/archive.sh index 601482c..2669757 100644 --- a/.config/bash/module/archive.sh +++ b/.config/bash/module/archive.sh @@ -1,51 +1,29 @@ export _archive_pattern="_[0-9]{12}-[[:alnum:]]{40}.t[xg]z" +export _archive_pattern_fast="_[0-9]{12}-[[:alnum:]]{40}.tgz" # Archive directories. # All directories by default. # Usage: archive [DIRS] function archive() { local IFS=$'\n' - local targets=("${@}") - local count=0 - local total=${#} - local date=$(_archive_date) - local failed=0 + local targets=(${@}) + [[ "${targets}" = "" ]] && targets=($(_ls_dir)) - # Set dafult value to target all directories. - if [[ "${targets}" = "" ]]; then - targets=($(ls --classify | grep /\$)) - total=${#targets[@]} - fi + process() { + local target=${1} + local date=$(_archive_date) - # iterate each target. - for target in "${targets[@]}"; do - # increment counter. - ((count++)) - - # status info. - local status="[${count}/${total}] ${target}" - echo -e "${color_bwhite}${status}${color_default}" - - local name=$(parse_camel "${target}") + # Parse name. + local name=$(parse_camel ${target}) # create archive. - local hash=$(tar -c "${target}" | pv -s $(/usr/bin/du -sb "${target}" | awk '{print $1}') | xz -9e | tee "${name}".txz | sha1sum | cut -d\ -f1) + local hash=$(tar -c ${target} | pv -s $(/usr/bin/du -sb ${target} | awk '{print $1}') | xz -9e | tee ${name}.txz | sha1sum | cut -d\ -f1) # append hash to target name. - mv "${name}".txz "${name}"_${date}-${hash}.txz + mv ${name}.txz ${name}_${date}-${hash}.txz + } - # Show error. - if [[ ${?} != 0 ]]; then - ((failed++)) - echo -e "${color_bred}${status}: Failed.${color_default}" - fi - done - - # Show error. - if [[ ${failed} != 0 ]]; then - echo -e "${color_bred}Failed: ${failed}.${color_default}" - false - fi + _iterate_targets process ${targets[@]} } # Archive directories with fast compression. @@ -54,26 +32,13 @@ function archive() { function archive_fast() { local IFS=$'\n' local targets=("${@}") - local count=0 - local total=${#} - local date=$(_archive_date) - local failed=0 + [[ "${targets}" = "" ]] && targets=($(_ls_dir)) - # Set dafult value to target all directories. - if [[ "${targets}" = "" ]]; then - targets=($(ls --classify | grep /$)) - total=${#targets[@]} - fi - - # iterate each target. - for target in "${targets[@]}"; do - # increment counter. - ((count++)) - - # status info. - local status="[${count}/${total}] ${target}" - echo -e "${color_bwhite}${status}${color_default}" + process() { + local target="${1}" + local date=$(_archive_date) + # Parse name. local name=$(parse_camel "${target}") # create archive. @@ -81,19 +46,9 @@ function archive_fast() { # append hash to target name. mv "${name}".tgz "${name}"_${date}-${hash}.tgz + } - # Show error. - if [[ $? != 0 ]]; then - ((failed++)) - echo -e "${color_bred}${status}: Failed.${color_default}" - fi - done - - # Show error. - if [[ ${failed} != 0 ]]; then - echo -e "${color_bred}Failed: ${failed}.${color_default}" - false - fi + _iterate_targets process ${targets[@]} } # Check archives integrity. @@ -101,44 +56,24 @@ function archive_fast() { # Usage: archive_check [FILES] function archive_check() { local IFS=$'\n' - local targets=("${@}") - local total=${#} - local count=0 - local failed=0 + local targets=(${@}) + [[ "${targets}" = "" ]] && targets=($(ls | grep -E ${_archive_pattern})) - # set dafult value to target all supported archives. - if [[ "${targets}" = "" ]]; then - targets=($(ls | grep -E ${_archive_pattern})) - total=${#targets[@]} - fi - - # iterate each target. - for target in "${targets[@]}"; do - # increment counter. - ((count++)) - - # status info. - local status="[${count}/${total}] ${target}" - echo -e "${color_bwhite}${status}${color_default}" + process() { + local target=${1} # extract hash from name. local data=($(_archive_parse ${target})) local saved=${data[2]} # calculate actual hash. - local actual=$(pv "${target}" | sha1sum | cut -d\ -f1) + local actual=$(pv ${target} | sha1sum | cut -d\ -f1) - # compare hashes, show error on mismatch. - if [[ "${actual}" != "${saved}" ]]; then - ((failed++)) - echo -e "${color_bred}${status}: Failed.${color_default}" - fi - done + # compare hashes. + [[ "${actual}" = "${saved}" ]] + } - if [[ ${failed} != 0 ]]; then - echo -e "${color_bred}Failed: ${failed}.${color_default}" - false - fi + _iterate_targets process ${targets[@]} } # Delete old versions of archives. @@ -146,167 +81,52 @@ function archive_check() { # Usage: archive_prune [NAME] function archive_prune() { local IFS=$'\n' - local targets=("${@}") - local count=0 - local total=${#} - local failed=0 - - # All archives by default. - if [[ "${targets}" = "" ]]; then - targets=($(ls | grep -E ${_archive_pattern})) - total=${#targets[@]} - fi - - # Iterate each target. - for target in "${targets[@]}"; do - # Only work with existing files. - [[ -f "${target}" ]] || continue - - # Iterate counter. - ((count++)) + local targets=(${@}) + [[ "${targets}" = "" ]] && targets=($(ls | grep -E ${_archive_pattern})) + process() { local data=($(_archive_parse ${target})) - local name="${data[0]}" - local time="${data[1]}" + local name=${data[0]} + local time=${data[1]} local copies=($(ls ${name}_*)) # Iterate each copy. - for copy in "${copies[@]}"; do + for copy in ${copies[@]}; do local copy_data=($(_archive_parse ${copy})) - local copy_time="${copy_data[1]}" + local copy_time=${copy_data[1]} if [[ "${copy_time}" -lt "${time}" ]]; then - echo -e "${name}: prune ${copy_time}." - rm -- "${copy}" - - if [[ ${?} != 0 ]]; then - echo -e "${color_bred}${target}: Failed.${color_default}" - ((failed++)) - fi + echo -e "${name}: Prune ${copy_time}." + rm -- ${copy} fi done - done + } - if [[ ${failed} != 0 ]]; then - echo -e "${color_bred}Failed: ${failed}.${color_default}" - false - fi -} - -# Rename archives. -# If no name specified, it simplifies archive's name. -# If no archives specified, apply to all archives. -# Usage: archive_name [ARCHIVE] [NAME] -function archive_name() { - local IFS=$'\n' - local targets="${1}" - local name="${2}" - local total=1 - local count=0 - local failed=0 - - # set dafult value to target all supported archives. - if [[ "${targets}" = "" ]]; then - targets=($(ls | grep -E ${_archive_pattern})) - total=${#targets[@]} - fi - - # iterate each target. - for target in "${targets[@]}"; do - # iterate counter. - ((count++)) - - # simplify name by default. - if [[ "${name}" = "" || ${count} -gt 1 ]]; then - name="${target%_*}" - name="$(parse_camel ${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_bwhite}${status}${color_default}" - continue - fi - - # check for existing target. - if [[ -f "${new_name}" ]]; then - echo -e "${color_bred}${status}: Already exists.${color_default}" - ((failed++)) - continue - fi - - echo -e "${color_bwhite}${status}${color_default}" - - # rename. - mv -- "${target}" "${new_name}" - - if [[ ${?} != 0 ]]; then - echo -e "${color_bred}${status}: Failed.${color_default}" - ((failed++)) - fi - done - - if [[ ${failed} != 0 ]]; then - echo -e "${color_bred}Failed: ${failed}.${color_default}" - false - fi + _iterate_targets process ${targets[@]} } # Delete specified or all archive files. # Usage: archive_rm [FILES] function archive_rm() { local IFS=$'\n' - local targets=("${@}") - local total=${#} - local count=0 - local failed=0 + local targets=(${@}) + [[ "${targets}" = "" ]] && targets=($(ls | grep -E ${_archive_pattern})) - # set dafult value to target all supported archives. - if [[ "${targets}" = "" ]]; then - targets=($(ls | grep -E ${_archive_pattern})) - total=${#targets[@]} - fi + process() { + rm -- "${1}" + } - # iterate each target. - for target in "${targets[@]}"; do - # increment counter. - ((count++)) - - # status info. - local status="[${count}/${total}] ${target}" - echo -e "${color_bwhite}${status}${color_default}" - - # Delete archive. - rm -- "${target}" - - # Show error. - if [[ ${?} != 0 ]]; then - ((failed++)) - echo -e "${color_bred}${status}: Failed.${color_default}" - fi - done - - # Show error. - if [[ ${failed} != 0 ]]; then - echo -e "${color_bred}Failed: ${failed}.${color_default}" - false - fi + _iterate_targets process ${targets[@]} } # Recompress previously created archive_fast with better compression. # Usage: archive_xz [FILES] function archive_xz() { - local targets="$(ls | grep -E ${_archive_pattern} | grep \.tgz\$)" + local IFS=$'\n' + local targets=("${@}") + [[ "${targets}" = "" ]] && targets=$(ls | grep -E ${_archive_pattern_fast}) - function process() { - local IFS=$'\n' + process() { local target="${1}" local data=($(_archive_parse "${target}")) local tmp="${data[0]}.txz" @@ -331,66 +151,33 @@ function archive_xz() { # Usage: unarchive [FILES] function unarchive() { local IFS=$'\n' - local targets=("${@}") - local count=0 - local total=${#} - local failed=0 - - # set dafult value to target all supported archives. - if [[ "${targets}" = "" ]]; then - targets=($(ls | grep -E ${_archive_pattern})) - total=${#targets[@]} - fi - - # iterate each target. - for target in "${targets[@]}"; do - # increment counter. - ((count++)) - - # status info. - local status="[${count}/${total}] ${target}" - echo -e "${color_bwhite}${status}${color_default}" + local targets=(${@}) + [[ "${targets}" = "" ]] && targets=$(ls | grep -E ${_archive_pattern}) + process() { # extract hash from name. - local data=($(_archive_parse "${target}")) - local saved="${data[2]}" + local data=($(_archive_parse ${target})) + local saved=${data[2]} # calculate actual hash. - local actual=$(pv "${target}" | sha1sum | cut -d\ -f1) + local actual=$(pv ${target} | sha1sum | cut -d\ -f1) # extract if hash matched or show error if not. if [[ "${saved}" = "${actual}" ]]; then - # figure out the compression tool. - local compressor case "${target##*.}" in "txz") - compressor="xz -d" + pv ${target} | xz -d | tar -xf - ;; "tgz") - compressor="gzip -d" + pv ${target} | gzip -d | tar -xf - ;; esac - - # extract. - unset IFS - pv "${target}" | ${compressor} | tar -xf - - - if [[ ${?} != 0 ]]; then - echo -e "${color_bred}${status}: Failed.${color_default}" - ((failed++)) - fi else - # report validation error & continue. - echo -e "${color_bred}${status}: Validation failed.${color_default}" - ((failed++)) - continue + false fi - done + } - if [[ ${failed} != 0 ]]; then - echo -e "${color_bred}Failed: ${failed}.${color_default}" - false - fi + _iterate_targets process ${targets[@]} } # Parse archive file name to get: name, date, hash and format. @@ -434,10 +221,16 @@ function _archive_grep() { _autocomplete_grep ${_archive_pattern} } +# Autocomplete with fast archives in current dir. +function _archive_grep_fast() { + _autocomplete_grep ${_archive_pattern_fast} +} + # Get date for a new archive. function _archive_date() { date +%Y%m%d%H%M } complete -o filenames -F _archive_grep archive_check unarchive archive_rm +complete -o filenames -F _archive_grep_fast archive_xz complete -o filenames -F _archive_name archive_name diff --git a/.config/bash/module/util.sh b/.config/bash/module/util.sh index 4ca03ab..3448fd6 100644 --- a/.config/bash/module/util.sh +++ b/.config/bash/module/util.sh @@ -31,11 +31,7 @@ function _iterate_targets() { ((count++)) # status info. - if [[ "${total}" -gt 1 ]]; then - local status="[${count}/${total}] ${target}" - else - local status="${target}" - fi + local status="[${count}/${total}] ${target}" echo -e "${color_bwhite}${status}${color_default}" # Call function.