compress_single() {
  local msg='Usage: compress_single [-h|--help]
compress_single [-t|--tar] [-n|--no-tar] [-p|--pad PAD] COMMAND SOURCE [TARGET]
If TARGET is not provided and PAD is provided, SOURCE concatenating PAD is used.
No tar is used by default.'
  local tar=0
  local pad=''
  local target=''
  while [ "$#" -gt 0 ]; do
    case "$1" in
      -h | --help)
        echo "$msg"
        return 0
        ;;
      -t | --tar)
        tar=1
        shift
        ;;
      -n | --no-tar)
        tar=0
        shift
        ;;
      -p | --pad)
        if [ "$#" -lt 2 ]; then
          echo "$msg" >&2
          return 1
        fi
        pad="$2"
        shift 2
        ;;
      --)
        shift
        break
        ;;
      *)
        break
        ;;
    esac
  done
  if [ "$#" -eq 3 ]; then
    target="$3"
  elif [ "$#" -eq 2 ] && [ -n "$pad" ]; then
    target="${2}${pad}"
  else
    echo "$msg" >&2
    return 1
  fi
  if [ "$tar" -eq 1 ]; then
    (
      set -o pipefail
      tar -cf - "$2" | __pv | $1 | __pv >"$target"
    )
  else
    (
      set -o pipefail
      $1 "$2" | __pv >"$target"
    )
  fi
}

split_file() {
  local bytes
  if [ -n "${SPLIT_SIZE:-}" ]; then
    bytes="$SPLIT_SIZE"
  else
    bytes="4000M"
  fi
  split -b "$bytes" -d -a 3 "$1" "$1.part."
}

compress_split() {
  # shellcheck disable=2016
  local msg='Usage: compress_split [-h|--help]
compress_split [-t|--tar] [-n|--no-tar] [-p|--pad PAD] [-b BYTES|--bytes BYTES] COMMAND SOURCE [TARGET]
If TARGET is not provided and PAD is provided, SOURCE concatenating PAD is used.
No tar is used by default.
If BYTES is not provided, $SPLIT_SIZE is used if set and 4000M is used otherwise.'
  local bytes
  local pad=''
  local target=''
  if [ -n "${SPLIT_SIZE:-}" ]; then
    bytes="$SPLIT_SIZE"
  else
    bytes="4000M"
  fi
  local tar=0
  while [ "$#" -gt 0 ]; do
    case "$1" in
      -h | --help)
        echo "$msg"
        return 0
        ;;
      -t | --tar)
        tar=1
        shift
        ;;
      -n | --no-tar)
        tar=0
        shift
        ;;
      -p | --pad)
        if [ "$#" -lt 2 ]; then
          echo "$msg" >&2
          return 1
        fi
        pad="$2"
        shift 2
        ;;
      -b | --bytes)
        if [ "$#" -lt 2 ]; then
          echo "$msg" >&2
          return 1
        fi
        bytes="$2"
        shift 2
        ;;
      --)
        shift
        break
        ;;
      *)
        break
        ;;
    esac
  done
  if [ "$#" -eq 3 ]; then
    target="$3"
  elif [ "$#" -eq 2 ] && [ -n "$pad" ]; then
    target="${2}${pad}"
  else
    echo "$msg" >&2
    return 1
  fi
  if [ "$tar" -eq 1 ]; then
    (
      set -o pipefail
      tar -cf - "$2" | __pv | $1 | __pv | split -b "$bytes" -d -a 3 - "$target.part."
    )
  else
    (
      set -o pipefail
      $1 "$2" | __pv | split -b "$bytes" -d -a 3 - "$target.part."
    )
  fi
}

bz2_single() {
  compress_single --tar --pad '.tar.bz2' 'bzip2 -9' "$@"
}

gz_single() {
  compress_single --tar --pad '.tar.gz' 'gzip -9' "$@"
}

xz_single() {
  compress_single --tar --pad '.tar.xz' 'xz -9' "$@"
}

tar_single() {
  compress_single --no-tar --pad '.tar' 'tar -cf -' "$@"
}

zip_single() {
  compress_single --no-tar --pad '.zip' 'zip -r -9 -' "$@"
}

bz2_split() {
  compress_split --tar --pad '.tar.bz2' 'bzip2 -9' "$@"
}

gz_split() {
  compress_split --tar --pad '.tar.gz' 'gzip -9' "$@"
}

xz_split() {
  compress_split --tar --pad '.tar.xz' 'xz -9' "$@"
}

tar_split() {
  compress_split --no-tar --pad '.tar' 'tar -cf -' "$@"
}

zip_split() {
  compress_split --no-tar --pad '.zip' 'zip -r -9 -' "$@"
}

extract_all_and() {
  (
    shopt -s globstar nullglob
    for f in **/*; do
      [[ -f $f ]] || continue
      local file=${f##*/}
      local dir=${f%/*}
      [[ $dir == "$f" ]] && dir=.
      local un=''
      local cmd=()
      case $file in
        *.rar)
          un=${file%.rar}
          cmd=(unrar x)
          ;;
        *.zip)
          un=${file%.zip}
          cmd=(unzip)
          ;;
        *.tar.gz)
          un=${file%.tar.gz}
          cmd=(tar -xzf)
          ;;
        *.tgz)
          un=${file%.tgz}
          cmd=(tar -xzf)
          ;;
        *.gz)
          un=${file%.gz}
          cmd=(gzip -d)
          ;;
        *.tar.bz2)
          un=${file%.tar.bz2}
          cmd=(tar -xjf)
          ;;
        *.tbz2)
          un=${file%.tbz2}
          cmd=(tar -xjf)
          ;;
        *.bz2)
          un=${file%.bz2}
          cmd=(bzip2 -d)
          ;;
        *.tar.xz)
          un=${file%.tar.xz}
          cmd=(tar -xJf)
          ;;
        *.txz)
          un=${file%.txz}
          cmd=(tar -xJf)
          ;;
        *.xz)
          un=${file%.xz}
          cmd=(xz -d)
          ;;
        *)
          continue
          ;;
      esac
      (
        cd "$dir" &&
          "${cmd[@]}" "$file" &&
          rm -- "$file" &&
          "$@" "$un" &&
          rm -rf -- "$un"
      )
    done
  )
}

extract_all() {
  extract_all_and false
}

extract_all_and_bz2() {
  extract_all_and bz2_single
}

extract_all_and_gz() {
  extract_all_and gz_single
}

extract_all_and_xz() {
  extract_all_and xz_single
}

extract_all_and_tar() {
  extract_all_and tar_single
}

extract_all_and_zip() {
  extract_all_and zip_single
}

extract_all_and_bz2_split() {
  extract_all_and bz2_split "$@"
}

extract_all_and_gz_split() {
  extract_all_and gz_split "$@"
}

extract_all_and_xz_split() {
  extract_all_and xz_split "$@"
}

extract_all_and_tar_split() {
  extract_all_and tar_split "$@"
}

extract_all_and_zip_split() {
  extract_all_and zip_split "$@"
}