Blame p7zip

Adrian Schröter 60546d
#!/bin/sh
Adrian Schröter 60546d
# gzip-like CLI wrapper for p7zip
Adrian Schröter 60546d
# version 3.0
Adrian Schröter 60546d
#
Adrian Schröter 60546d
# History
Adrian Schröter 60546d
#  2.0 :
Adrian Schröter 60546d
#    - support for -filename, "file name"
Adrian Schröter 60546d
#    - p7zip file1 file2 ...
Adrian Schröter 60546d
#  3.0 :  (robert@debian.org, March 2016)
Adrian Schröter 60546d
#    - use 7za or 7zr, whichever one is available
Adrian Schröter 60546d
#    - refactor the script for better readability
Adrian Schröter 60546d
#    - remove `"$?" != 0 ' checks that do not work with `set -e'
Adrian Schröter 60546d
#    - use stderr for error reporting
Adrian Schröter 60546d
#    - add support for -c, -f, -k options
Adrian Schröter 60546d
Adrian Schröter 60546d
set -e
Adrian Schröter 60546d
Adrian Schröter 60546d
# detect 7z program to use
Adrian Schröter 60546d
prg7z="`which 7za 2>/dev/null`" || \
Adrian Schröter 60546d
  prg7z="`which 7zr 2>/dev/null`" || \
Adrian Schröter 60546d
    { echo "$0: cannot find neither 7za nor 7zr command" >&2; exit 1; }
Adrian Schröter 60546d
Adrian Schröter 60546d
# global options
Adrian Schröter 60546d
f_compress=true
Adrian Schröter 60546d
f_keep=false
Adrian Schröter 60546d
f_force=false
Adrian Schröter 60546d
f_tostdout=false
Adrian Schröter 60546d
Adrian Schröter 60546d
usage()
Adrian Schröter 60546d
{
Adrian Schröter 60546d
  echo "Usage: $0 [options] [--] [ name ... ]"
Adrian Schröter 60546d
  echo ""
Adrian Schröter 60546d
  echo "Options:"
Adrian Schröter 60546d
  echo "    -c --stdout --to-stdout      output data to stdout"
Adrian Schröter 60546d
  echo "    -d --decompress --uncompress decompress file"
Adrian Schröter 60546d
  echo "    -f --force                   do not ask questions"
Adrian Schröter 60546d
  echo "    -k --keep                    keep original file"
Adrian Schröter 60546d
  echo "    -h --help                    print this help"
Adrian Schröter 60546d
  echo "    --                           treat subsequent arguments as file"
Adrian Schröter 60546d
  echo "                                 names, even if they start with a dash"
Adrian Schröter 60546d
  echo ""
Adrian Schröter 60546d
  exit 0
Adrian Schröter 60546d
}
Adrian Schröter 60546d
Adrian Schröter 60546d
has_7z_suffix()
Adrian Schröter 60546d
{
Adrian Schröter 60546d
  case "$1" in
Adrian Schröter 60546d
    *.7z)
Adrian Schröter 60546d
      return 0
Adrian Schröter 60546d
      ;;
Adrian Schröter 60546d
    *)
Adrian Schröter 60546d
      return 1
Adrian Schröter 60546d
      ;;
Adrian Schröter 60546d
  esac;
Adrian Schröter 60546d
}
Adrian Schröter 60546d
Adrian Schröter 60546d
make_tmp_file()
Adrian Schröter 60546d
{
Adrian Schröter 60546d
  P7ZIPTMP="${TMP:-/tmp}"
Adrian Schröter 60546d
  mktemp "${P7ZIPTMP}/p7zip.XXXXXXXX"
Adrian Schröter 60546d
}
Adrian Schröter 60546d
Adrian Schröter 60546d
check_not_a_tty()
Adrian Schröter 60546d
{
Adrian Schröter 60546d
  if ! ${f_force} && ${f_compress} && tty <&1 >/dev/null ; then
Adrian Schröter 60546d
    echo "$0: compressed data not written to a terminal." >&2
Adrian Schröter 60546d
    echo "For help, type: $0 -h" >&2
Adrian Schröter 60546d
    exit 1
Adrian Schröter 60546d
  fi
Adrian Schröter 60546d
}
Adrian Schröter 60546d
Adrian Schröter 60546d
compress_file()
Adrian Schröter 60546d
{
Adrian Schröter 60546d
  file="$1"
Adrian Schröter 60546d
Adrian Schröter 60546d
  if ! ${f_force} && has_7z_suffix "${file}"; then
Adrian Schröter 60546d
    echo "$0: $file already has the 7z suffix" >&2
Adrian Schröter 60546d
    exit 1
Adrian Schröter 60546d
  fi
Adrian Schröter 60546d
Adrian Schröter 60546d
  # compress to stdout via temporary file
Adrian Schröter 60546d
  if ${f_tostdout}; then
Adrian Schröter 60546d
    check_not_a_tty
Adrian Schröter 60546d
    tmp="`make_tmp_file`"
Adrian Schröter 60546d
    trap "rm -f -- ${tmp}" 0
Adrian Schröter 60546d
    rm -f -- "${tmp}"
Adrian Schröter 60546d
    "${prg7z}" a -si -- "${tmp}" < "${file}" >/dev/null && cat "${tmp}" || \
Adrian Schröter 60546d
      { echo "$0: failed to compress data to temporary file" >&2;  exit 1; }
Adrian Schröter 60546d
    rm -f -- "${tmp}"
Adrian Schröter 60546d
    return 0
Adrian Schröter 60546d
  fi
Adrian Schröter 60546d
Adrian Schröter 60546d
  # compress to a file
Adrian Schröter 60546d
  if ! ${f_force} && [ -e "${file}.7z" ]; then
Adrian Schröter 60546d
    echo "$0: destination file ${file}.7z already exists" >&2
Adrian Schröter 60546d
    exit 1
Adrian Schröter 60546d
  fi
Adrian Schröter 60546d
Adrian Schröter 60546d
  rm -f -- "${file}.7z"
Adrian Schröter 60546d
  flags=""
Adrian Schröter 60546d
  ${f_keep} || flags="$flags -sdel"
Adrian Schröter 60546d
  ! ${f_force} || flags="$flags -y"
Adrian Schröter 60546d
  "${prg7z}" a $flags -- "${file}.7z" "${file}" || {  rm -f -- "${file}.7z"; exit 1; }
Adrian Schröter 60546d
}
Adrian Schröter 60546d
Adrian Schröter 60546d
Adrian Schröter 60546d
decompress_file()
Adrian Schröter 60546d
{
Adrian Schröter 60546d
  file="$1"
Adrian Schröter 60546d
Adrian Schröter 60546d
  has_7z_suffix "${file}" || { echo "$0: ${file}: unknown suffix" >&2; exit 1; }
Adrian Schröter 60546d
Adrian Schröter 60546d
  # decompress to stdout
Adrian Schröter 60546d
  if ${f_tostdout}; then
Adrian Schröter 60546d
    # The following `| cat' pipe shouldn't be needed, however it is here to
Adrian Schröter 60546d
    # trick 7z not to complain about writing data to terminal.
Adrian Schröter 60546d
    "${prg7z}" x -so -- "${file}" | cat || exit 1
Adrian Schröter 60546d
    return 0;
Adrian Schröter 60546d
  fi
Adrian Schröter 60546d
Adrian Schröter 60546d
  flags=""
Adrian Schröter 60546d
  ! ${f_force} || flags="$flags -y"
Adrian Schröter 60546d
  "${prg7z}" x $flags -- "${file}" || exit 1
Adrian Schröter 60546d
Adrian Schröter 60546d
  # remove original file unless the archive contains more than one file
Adrian Schröter 60546d
  if ! ${f_keep} && "${prg7z}" l --  "${file}" 2>/dev/null | grep -q '^1 file,' 2>/dev/null; then
Adrian Schröter 60546d
    rm -f -- "${file}"
Adrian Schröter 60546d
  fi
Adrian Schröter 60546d
}
Adrian Schröter 60546d
Adrian Schröter 60546d
process_file()
Adrian Schröter 60546d
{
Adrian Schröter 60546d
  file="$1"
Adrian Schröter 60546d
Adrian Schröter 60546d
  # check if file exists and is readable
Adrian Schröter 60546d
  [ -r "${file}" ] || { echo "$0: cannot read ${file}" >&2; exit 1; }
Adrian Schröter 60546d
Adrian Schröter 60546d
  if ${f_compress}; then
Adrian Schröter 60546d
    compress_file "${file}"
Adrian Schröter 60546d
  else
Adrian Schröter 60546d
    decompress_file "${file}"
Adrian Schröter 60546d
  fi
Adrian Schröter 60546d
}
Adrian Schröter 60546d
Adrian Schröter 60546d
process_stdin()
Adrian Schröter 60546d
{
Adrian Schröter 60546d
  check_not_a_tty
Adrian Schröter 60546d
Adrian Schröter 60546d
  tmp="`make_tmp_file`"
Adrian Schröter 60546d
  trap "rm -f -- ${tmp}" 0
Adrian Schröter 60546d
Adrian Schröter 60546d
  if ${f_compress}; then
Adrian Schröter 60546d
Adrian Schröter 60546d
    rm -f -- "${tmp}"
Adrian Schröter 60546d
    "${prg7z}" a -si -- "${tmp}" >/dev/null && cat -- "${tmp}" || exit 1
Adrian Schröter 60546d
Adrian Schröter 60546d
  else # decompress
Adrian Schröter 60546d
Adrian Schröter 60546d
    cat > "${tmp}"
Adrian Schröter 60546d
    # The following `| cat' pipe shouldn't be needed, however it is here to
Adrian Schröter 60546d
    # trick 7z not to complain about writing data to terminal.
Adrian Schröter 60546d
    "${prg7z}" x -so -- "${tmp}" | cat || exit 1
Adrian Schröter 60546d
  fi
Adrian Schröter 60546d
Adrian Schröter 60546d
  rm -f -- "${tmp}"
Adrian Schröter 60546d
}
Adrian Schröter 60546d
Adrian Schröter 60546d
Adrian Schröter 60546d
## MAIN
Adrian Schröter 60546d
Adrian Schröter 60546d
Adrian Schröter 60546d
# files and flags
Adrian Schröter 60546d
while [ "$#" != "0" ] ; do
Adrian Schröter 60546d
  case "$1" in
Adrian Schröter 60546d
    -c|--stdout|--to-stdout)
Adrian Schröter 60546d
      f_tostdout=true
Adrian Schröter 60546d
      ;;
Adrian Schröter 60546d
    -d|--decompress|--uncompress)
Adrian Schröter 60546d
      f_compress=false # decompressing
Adrian Schröter 60546d
      ;;
Adrian Schröter 60546d
    -f|--force)
Adrian Schröter 60546d
      f_force=true
Adrian Schröter 60546d
      ;;
Adrian Schröter 60546d
    -h|--help)
Adrian Schröter 60546d
      usage
Adrian Schröter 60546d
      ;;
Adrian Schröter 60546d
    -k|--keep)
Adrian Schröter 60546d
      f_keep=true
Adrian Schröter 60546d
      ;;
Adrian Schröter 60546d
    --)
Adrian Schröter 60546d
      shift
Adrian Schröter 60546d
      break
Adrian Schröter 60546d
      ;;
Adrian Schröter 60546d
    -*)
Adrian Schröter 60546d
      echo "$0: ignoring unknown option $1" >&2
Adrian Schröter 60546d
      ;;
Adrian Schröter 60546d
    *)
Adrian Schröter 60546d
      break
Adrian Schröter 60546d
      ;;
Adrian Schröter 60546d
  esac
Adrian Schröter 60546d
  shift
Adrian Schröter 60546d
done
Adrian Schröter 60546d
Adrian Schröter 60546d
Adrian Schröter 60546d
# make sure they're present, before we screw up
Adrian Schröter 60546d
for i in mktemp rm cat tty grep; do
Adrian Schröter 60546d
  if ! which $i >/dev/null ; then
Adrian Schröter 60546d
    echo "$0: $i: command not found" >&2
Adrian Schröter 60546d
    exit 1
Adrian Schröter 60546d
  fi
Adrian Schröter 60546d
done
Adrian Schröter 60546d
Adrian Schröter 60546d
if [ "$#" = 0 ]; then
Adrian Schröter 60546d
  # compressing/decompressing using standard I/O
Adrian Schröter 60546d
  process_stdin
Adrian Schröter 60546d
  exit 0
Adrian Schröter 60546d
fi
Adrian Schröter 60546d
Adrian Schröter 60546d
# only files now
Adrian Schröter 60546d
while [ "$#" != "0" ] ; do
Adrian Schröter 60546d
  process_file  "$1"
Adrian Schröter 60546d
  shift
Adrian Schröter 60546d
done
Adrian Schröter 60546d
Adrian Schröter 60546d
exit 0