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