Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:aspiers
unpack
unpack
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File unpack of Package unpack
#!/bin/bash # # Unpacks one of several different types of archive to the current # directory. If there is more than one entry in the top-level # directory, automatically creates a new subdirectory and unpacks to # that, in order to avoid filling the current directory with crap. # In every case, informs the user where the unpacked contents ended up. # # Adam Spiers <shell-hacks@adamspiers.org> me="`basename $0`" warn () { echo >&2 "$*" } die () { warn "$*" exit 1 } abort () { die "$*; aborting." } interactive_mode () { [ -t 1 ] } progress () { if interactive_mode; then echo "$@" fi } usage () { cat <<EOF >&2 Usage: $me ARCHIVE Unpacks the given archive. Supported formats include: tar (incl. compressed with gzip, bzip2, xz), zip, 7z, rar, apk, xpi, jar, class, gem, box, rpm Guarantees that extraction will always be to a newly-created directory rather than polluting an existing one with multiple entries. If STDOUT is not a tty, only the name of the new directory containing the unpacked archive will be output to STDOUT. This can then be captured and reused programmatically in other scripts. EOF exit 1 } parse_args () { if [ "$1" == -h ] || [ "$1" == --help ] || [ -z "$1" ]; then usage fi archive_path="$1" archive="`basename \"$1\"`" if ! [ -e "$archive_path" ]; then abort "$archive_path does not exist" fi } get_ideal_dest_dir () { ideal_dest_dir= case "$archive" in *.tar|*.tgz|*.tbz|*.txz|*.zip|*.Zip|*.ZIP|\ *.7z|*.apk|*.rar|*.xpi|*.jar|*.sar|*.class|\ *.job|*.pylib|*.gem|*.box|*.rpm) ideal_dest_dir="${archive%.*}" ;; *.tar.gz) ideal_dest_dir="${archive%.tar.gz}" ;; *.tar.bz2) ideal_dest_dir="${archive%.tar.bz2}" ;; *.tar.xz) ideal_dest_dir="${archive%.tar.xz}" ;; *) abort "$archive does not have a supported file extension" ;; esac } # Runs external commands, redirecting output as required. run () { if interactive_mode; then "$@" else "$@" >&2 fi } extract () { if ! tmpdir=`mktemp -d "$ideal_dest_dir.tmp.XXXXXXXX"`; then die "mktemp failed: $!" fi case "$archive" in *.tar) run tar -C "$tmpdir" -xvf "$archive_path" ;; *.tar.gz|*.tgz|*.box) run tar -C "$tmpdir" -zxvf "$archive_path" ;; *.tar.bz2|*.tbz) run tar -C "$tmpdir" -jxvf "$archive_path" ;; *.tar.xz|*.txz) run tar -C "$tmpdir" -Jxvf "$archive_path" ;; *.zip|*.ZIP|*.Zip|*.xpi|*.jar|*.class|*.sar|*.job|*.pylib|*.apk) run unzip -d "$tmpdir" "$archive_path" ;; *.7z) run 7za x -o"$tmpdir" "$archive_path" ;; *.gem) run gem unpack --target="$tmpdir" "$archive_path" ;; *.rar) archive_abspath=$( abs "$archive_path" ) pushd "$tmpdir" run unrar x "$archive_abspath" popd ;; *.rpm) rpm="$archive_path" rpm_name="${rpm%.rpm}" rpm_name="${rpm_name##*/}" cpio="$rpm_name.cpio" progress -n "Extracting cpio to $tmpdir/$cpio ... " rpm2cpio "$rpm" > "$tmpdir/$cpio" progress "done." progress -n "Unpacking cpio into $tmpdir ... " mkdir "$tmpdir/$rpm_name" cd "$tmpdir/$rpm_name" cpio -id < ../"$cpio" progress "done." rm ../"$cpio" ;; *) abort "$archive is not a supported archive format" ;; esac if [ $? != 0 ]; then abort "Unpack of $archive_path failed" fi } ensure_single_dir () { num_dirents=$( ls -A "$tmpdir" | wc -l ) if [ "$num_dirents" -eq 0 ]; then die "$archive was empty? Aborting" fi if [ "$num_dirents" -gt 1 ]; then # Naughty archive creator! Would cause a mess if unpacked to cwd. progress "$archive had more than one top-level entry" unpacked_dir="$tmpdir" else progress "$archive is clean; everything under a single top-level directory" top_dir=$( ls -A "$tmpdir" ) unpacked_dir="$tmpdir/$top_dir" if [ -e "$top_dir" ]; then warn "$top_dir already exists" else if mv "$unpacked_dir" .; then dest_dir="$top_dir" rmdir "$tmpdir" return else abort "mv $unpacked_dir . failed" fi fi fi calc_dest_dir rename_to_dest_dir } calc_dest_dir () { if ! [ -e "$ideal_dest_dir" ]; then # safe to use ideal choice of destination directory dest_dir="$ideal_dest_dir" else warn "Ideal destination $ideal_dest_dir already exists" dest_dir="$archive.unpacked" if [ -e "$dest_dir" ]; then warn "$dest_dir also already exists" # Couldn't find a better place to move unpacked directory to, so # leave it where it already is. dest_dir="$unpacked_dir" fi fi } rename_to_dest_dir () { if [ "$unpacked_dir" != "$dest_dir" ]; then #progress "mv $unpacked_dir $dest_dir OK" if ! mv "$unpacked_dir" "$dest_dir"; then abort "mv $unpacked_dir $dest_dir failed" fi [ -d "$tmpdir" ] && rmdir "$tmpdir" fi } main () { parse_args "$@" get_ideal_dest_dir saved_dir="`pwd`" extract cd "$saved_dir" ensure_single_dir progress "Look inside $dest_dir" if ! [ -t 1 ]; then echo "$dest_dir" fi } main "$@"
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor