#!/bin/bash # # Copyright (C) 2013-2015, 2017, 2020, 2023 Etersoft # Copyright (C) 2013-2015, 2017, 2020, 2023 Vitaly Lipatov <lav@etersoft.ru> # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # PROGDIR=$(dirname $0) [ "$PROGDIR" = "." ] && PROGDIR=$(pwd) # will replaced to /usr/share/erc during install SHAREDIR=$(dirname $0) load_helper() { local CMD="$SHAREDIR/$1" [ -r "$CMD" ] || fatal "Have no $CMD helper file" . $CMD } load_helper erc-sh-functions load_helper erc-sh-archive check_tty # 1.zip tar: -> 1.tar build_target_name() { is_target_format $2 && echo $(get_archive_name "$1").${2/:/} && return echo "$1" return 1 } # TODO: list of $HAVE_7Z supported (see list_formats) # target file1 [file2...] create_archive() { local arc="$1" shift if have_patool ; then docmd patool $verbose create "$arc" "$@" return fi # FIXME: get type by ext only local type="$(get_archive_type "$arc")" case "$type" in *) docmd $HAVE_7Z a $arc "$@" #fatal "Not yet supported creating of $type archives" ;; esac } extract_archive() { local arc="$1" shift if have_patool ; then docmd patool $verbose extract "$arc" "$@" return fi local type="$(get_archive_type "$arc")" arc="$(realpath "$arc")" tdir=$(mktemp -d $(pwd)/UXXXXXXXX) && cd "$tdir" || fatal local TSUBDIR="$(basename "$arc" .$type)" case "$type" in tar.*) # TODO: check if there is only one file? # use subdir if there is no subdir in archive TSUBDIR="$(basename "$arc" $(echo $type | sed -e 's|^tar||') )" docmd $HAVE_7Z x -so $arc | docmd $HAVE_7Z x -si -ttar ;; *) docmd $HAVE_7Z x $arc "$@" #fatal "Not yet supported extracting of $type archives" ;; esac cd - >/dev/null # if only one dir in the subdir if [ -e "$(echo $tdir/*)" ] ; then mv $tdir/* . rmdir $tdir else mv $tdir "$TSUBDIR" fi } list_archive() { local arc="$1" shift # TODO: move to patool if [ "$(get_archive_type "$arc" 2>/dev/null)" = "exe" ] ; then docmd $HAVE_7Z l "$arc" || fatal return fi if have_patool ; then docmd patool $verbose list "$arc" "$@" return fi local type="$(get_archive_type "$arc")" case "$type" in *) docmd $HAVE_7Z l $arc "$@" #fatal "Not yet supported listing of $type archives" ;; esac } test_archive() { local arc="$1" shift # TODO: move to patool if [ "$(get_archive_type "$arc" 2>/dev/null)" = "exe" ] ; then docmd $HAVE_7Z t "$arc" || fatal return fi if have_patool ; then docmd patool $verbose test "$arc" "$@" return fi local type="$(get_archive_type "$arc")" case "$type" in *) docmd $HAVE_7Z t $arc "$@" #fatal "Not yet supported test of $type archives" ;; esac } repack_archive() { if have_patool ; then docmd patool $verbose repack "$1" "$2" return fi # TODO: if both have tar, try unpack | pack local ftype="$(get_archive_type "$1")" local ttype="$(get_archive_type "$2")" case "$ftype-$ttype" in tar.*-tar) docmd $HAVE_7Z x -so "$1" > "$2" ;; tar-tar.*) docmd $HAVE_7Z a -si "$2" < "$1" ;; tar.*-tar.*) docmd $HAVE_7Z x -so "$1" | $HAVE_7Z a -si "$2" ;; *) fatal "Not yet supported repack of $ftype-$ttype archives" ;; esac } phelp() { echo "$Descr $Usage Commands: $(get_help HELPCMD) Options: $(get_help HELPOPT) Examples: # erc dir - pack dir to dirname.zip # erc a archive.zip file(s)... - pack files to archive.zip # erc [x] archive.zip - unpack # unerc archive.zip - unpack # erc [repack] archive1.zip... archive2.rar $HAVE_7Z: - repack all to $HAVE_7Z # erc -f [repack] archive.zip archive.$HAVE_7Z - force repack zip to $HAVE_7Z (override target in anyway) # erc file/dir zip: - pack file to zip " } print_version() { echo "Etersoft archive manager version @VERSION@" echo "Copyright (c) Etersoft 2013-2023" echo "This program may be freely redistributed under the terms of the GNU AGPLv3." } progname="${0##*/}" Usage="Usage: $progname [options] [<command>] [params]..." Descr="erc - universal archive manager" progname="${0##*/}" force= target= verbose=--verbose use_7z= use_patool= if [ -z "$" ] ; then echo "Etersoft archive manager version @VERSION@" >&2 echo "Run $0 --help to get help" >&2 exit 1 fi while [ -n "$1" ] ; do case "$1" in -h|--help|help) # HELPOPT: this help phelp exit ;; -V|--version) # HELPOPT: print version print_version exit ;; -q|--quiet) # HELPOPT: be silent verbose= ;; -f|--force) # HELPOPT: override target force=-f ;; --use-patool) # HELPOPT: force use patool as backend use_patool=1 ;; --use-7z) # HELPOPT: force use 7z as backend use_7z=1 ;; -*) fatal "Unknown option '$1'" ;; *) break ;; esac shift done set_backend cmd="$1" eval lastarg=\${$#} # Just printout help if run without args if [ -z "$cmd" ] ; then print_version echo fatal "Run $ $progname --help for get help" fi # if the first arg is some archive, suggest extract if get_archive_type "$cmd" 2>/dev/null >/dev/null ; then if is_target_format $lastarg ; then cmd=repack else cmd=extract fi # erc dir (pack to zip by default) elif [ -d "$cmd" ] && [ -z "$2" ] ; then cmd=pack target=$(basename "$1").zip # erc dir zip: elif test -r "$1" && is_target_format "$2" ; then cmd=pack elif [ "$progname" = "unerc" ] ; then cmd=extract else shift fi # TODO: Если программа-архиватор не установлена, предлагать установку с помощью epm case $cmd in a|-a|create|pack|add) # HELPCMD: create archive / add file(s) to archive # TODO: realize archive addition if already exist (and separate adding?) if [ -z "$target" ] && is_target_format $lastarg ; then [ $# = 2 ] || fatal "Need two args" target="$(build_target_name "$1" "$2")" # clear last arg set -- "${@:1:$(($#-1))}" fi [ -z "$target" ] && target="$1" && shift [ -e "$target" ] && [ -n "$force" ] && docmd rm -f "$target" create_archive "$target" "$@" ;; e|x|-e|-x|u|-u|extract|unpack) # HELPCMD: extract files from archive # TODO: move to patool if [ "$(get_archive_type "$1" 2>/dev/null)" = "exe" ] ; then docmd $HAVE_7Z x "$1" exit fi extract_archive "$@" ;; # TODO: implement deletion # d|delete) # HELPCMD: delete file(s) from archive # docmd patool delete "$@" # ;; l|-l|list) # HELPCMD: list archive contents list_archive "$@" ;; t|-t|test|check) # HELPCMD: test for archive integrity test_archive "$@" ;; type) # HELPCMD: print type of archive get_archive_type "$1" || fatal "Can't recognize $1 as archive" ;; diff) # HELPCMD: compare two archive # check 2 arg docmd patool $verbose diff "$@" ;; b|-b|bench|benchmark) # HELPCMD: do CPU benchmark #assure_cmd $HAVE_7Z # TODO: can be $HAVE_7Za? docmd $HAVE_7Z b ;; search|grep) # HELPCMD: search in files from archive docmd patool $verbose search "$@" ;; repack|conv) # HELPCMD: convert source archive to target # TODO: need repack remove source file? # TODO: check for 2 arg if ! is_target_format $lastarg ; then [ $# = 2 ] || fatal "Need two args" [ "$(realpath "$1")" = "$(realpath "$2")" ] && warning "Output file is the same as input" && exit [ -e "$2" ] && [ -n "$force" ] && docmd rm -f "$2" repack_archive "$1" "$2" exit fi # add support for target zip: for i in "$@" ; do [ "$i" = "$lastarg" ] && continue target="$(build_target_name "$i" "$lastarg")" [ "$(realpath "$1")" = "$(realpath "$target")" ] && warning "Output file is the same as input" && exit [ -e "$target" ] && [ -n "$force" ] && docmd rm -f "$target" repack_archive "$i" "$target" || exit done ;; formats) # HELPCMD: lists supported archive formats # TODO: print allowed with current programs separately if [ -n "$verbose" ] && have_patool ; then docmd patool formats "$@" echo "Also we supports:" ( list_subformats ; list_extraformats ) | sed -e "s|^| |" else list_formats fi ;; *) # TODO: If we have archive in parameter, just unpack it fatal "Unknown command $1" ;; esac