#!/bin/bash # Hacky wrapper which tries to sensibly untar the file(s) it's passed. The # archives may optionally be .Z, .bz2 or .gz compressed (the file extension need # not indicate this). Zip, rar, cpio, deb and rpm archives are also supported # (provided the necessary utilities are available). Each archive should always # unpack into a single subdirectory of the current location. If the contents of # an archive would naturally dump into a single subdirectory it isn't nested # into a new one. # # Limitations: # - Robustness: 1) error checking limited. 2) I probably assume too much # about the output of the utilities I call. # - You cannot unpack standard input, just files # - It's up to you to check the clobbering behaviour will be what you want. # # Iain Murray 2005. set -e TAR=tar UNRAR=unrar # functions to give a list of archive contents function tarZlist { uncompress -c "$1" | "$TAR" t; } function tarbz2list { bzcat "$1" | "$TAR" t; } function targzlist { "$TAR" ztf "$1"; } function tarlist { "$TAR" tf "$1"; } function rarlist { "$UNRAR" vb "$1"; } function rpmlist { rpm2cpio "$1" | cpio -t --quiet; } # Warning: deblist is a fragile hack, which will probably break function deblist { dpkg-deb -c "$1" | sed 's/^[^ ]* *[^ ]* *[^ ]* *[^ ]* *[^ ]* *//'; } function cpiolist { cpio -t --quiet < "$1"; } # Fragile hack if don't have zipinfo: #function tarziplist { unzip -lqq "$1" | sed 's/^ *[0-9]* *[0-9\-]* *[0-9:]* *//'; } function tarziplist { zipinfo -1 "$1"; } # functions that actually do the business function untarZ { uncompress -c "$1" | "$TAR" x; } function untarbz2 { bzcat "$1" | "$TAR" x; } function untargz { "$TAR" zxf "$1"; } function untar { "$TAR" xf "$1"; } function myunrar { "$UNRAR" x -ap. "$1"; } function unrpm { rpm2cpio "$1" | cpio -i --no-absolute-filenames -d --quiet; } function undeb { dpkg-deb -x "$1" .; } function uncpio { cpio -i --no-absolute-filenames -d --quiet < "$1"; } function untarzip { unzip "$1"; } for a in "$@" ; do if [ -e "$a" ] ; then INFO=$(file "$a") else echo "$0: $a does not exist." exit 1 fi # Set suitable functions for this file. # BUG: could match text in filename. I don't care enough to fix. if echo $INFO | grep 'gzip compressed' > /dev/null ; then # gzipped (.gz, .tgz) tars listfunc=targzlist exfunc=untargz elif echo $INFO | grep "compress'd" > /dev/null ; then # compressed (.Z) tars listfunc=tarZlist exfunc=untarZ elif echo $INFO | grep "Zip archive" > /dev/null ; then # zip archive listfunc=tarziplist exfunc=untarzip elif echo $INFO | grep "bzip2 compressed" > /dev/null ; then # bzip2ed (.bz2) tar listfunc=tarbz2list exfunc=untarbz2 elif echo $INFO | grep "RAR archive" > /dev/null ; then # (.rar) listfunc=rarlist exfunc=myunrar elif echo $INFO | grep ": RPM " > /dev/null ; then # (.rpm) listfunc=rpmlist exfunc=unrpm elif echo $INFO | grep "cpio archive" > /dev/null ; then # (.cpio) listfunc=cpiolist exfunc=uncpio elif echo $INFO | grep "Debian .* package" > /dev/null ; then # (.cpio) listfunc=deblist exfunc=undeb else # otherwise hope plain tar can deal listfunc=tarlist exfunc=untar fi # unpack (construct a suitable subdirectory if necessary) IFS=" " out_dir=`$listfunc "$a" | sed -e 's/^\.\///' -e 's/\/.*//g' -e '/^$/d' | uniq` if [ `echo $out_dir | wc -l` -eq 1 ] ; then $exfunc "$a" else out_dir="$a"_contents out_dir=`echo $out_dir | sed -e 's/.*\///' \ -e 's/\(\.tar\|\.tar\.gz\|\.taz\|\.tar\.Z\|\.tgz\|\.tar\.bz2\|\.zip\|\.jar\|\.rar\|\.rpm\|\.cpio\|\.deb\)_contents$//i'` mkdir "$out_dir" cd "$out_dir" if echo "$a" | grep '^\/' > /dev/null ; then $exfunc "$a" else $exfunc ../"$a" fi cd .. fi echo Extracted $a to $out_dir done