Advertisement
MestreLion

debextract - wrapper to dpkg-deb -x for multiple filenames

Mar 13th, 2012
146
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 6.13 KB | None | 0 0
  1. #!/bin/bash
  2. #
  3. # debextract - Wrapper to "dpkg-deb -x" for multiple files
  4. #
  5. #    Copyright (C) 2012 Rodrigo Silva (MestreLion) <[email protected]>
  6. #
  7. #    This program is free software: you can redistribute it and/or modify
  8. #    it under the terms of the GNU General Public License as published by
  9. #    the Free Software Foundation, either version 3 of the License, or
  10. #    (at your option) any later version.
  11. #
  12. #    This program is distributed in the hope that it will be useful,
  13. #    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. #    GNU General Public License for more details.
  16. #
  17. #    You should have received a copy of the GNU General Public License
  18. #    along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>
  19. #
  20. # Wrapper to extract multiple debian packages (*.deb). It automatically chooses
  21. # a destination directory based on the deb's filename and also extracts the
  22. # control information files (the DEBIAN directory inside the package)
  23.  
  24. usage() {
  25. cat <<- USAGE
  26.     Usage: $self [${main} options] [options] FILE...
  27. USAGE
  28. if [[ "$1" ]] ; then
  29.     cat <<- USAGE
  30.         Try '$self --help' for more information.
  31.     USAGE
  32.     exit 1
  33. fi
  34. cat <<-USAGE
  35.  
  36.     Extracts Debian Package files (.deb) to a directory matching their filenames
  37.  
  38.     Options:
  39.     -h|--help     - show this page.
  40.     -v|--verbose  - print more details about what is being done. Also enables
  41.                      verbosity for ${main}. Use -X/+X to enable or disable this
  42.     -X|--vextract - turns ON  verbosity for ${main}. Useful if -v is not set
  43.     +X            - turns OFF verbosity for ${main}. Useful if -v is set
  44.     --destdir DIR - sets a directory for extraction of all packages. If ommited
  45.                      or blank, destination will be each package's current
  46.                      directory. In all cases, package filename will be appended
  47.                      to the final destination path.
  48.     --nocontrol      - do not extract the control files. (DEBIAN directory)
  49.     --controldir DIR - set the destination directory for the control files,
  50.                         relative to the extracted package directory. Ignored if
  51.                         --nocontrol is set. Default is DEBIAN.
  52.     --onerror ACTION - What to do if an error occur when executing $main for a
  53.                         given file. Valid ACTION values are:
  54.               skip     - skip error and continue with next file, if any
  55.               quit     - quit immediately, do not extract any further files
  56.               ask      - if not last file, ask user what to do. Default action
  57.                        Regardless of the action chosen, in case of any error
  58.                        $self will always exit with ${main}'s last unsucessfull
  59.                        exit code
  60.     ${main} options:
  61.                   - see ${main} --help or man ${main}
  62.  
  63.     FILE...       - package file(s) to extract, multiple files accepted
  64.  
  65.     The destination directory for extraction of each package will be the package
  66.     filename without its extension (usually .deb). If the filename  has no
  67.     extension, an error will occur, since this would be the same as executing
  68.     ${main} -x file file
  69.  
  70.     Copyright (C) 2012 Rodrigo Silva (MestreLion) <[email protected]>
  71.     License: GPLv3 or later. See <http://www.gnu.org/licenses/gpl.html>
  72. USAGE
  73. exit 0
  74. }
  75.  
  76. opterror() { echo "$self: $1" ; usage 1 ; }
  77. missing()  { opterror "missing ${1:+$1 }operand" ; }
  78.  
  79. testaction() {
  80.     [[ "$1" ]] || missing "action"
  81.     actions=( skip quit ask )
  82.     for action in "${actions[@]}"; do [[ "$action" == "$1" ]] && return ; done
  83.     opterror "invalid action '$1'. valid options are: ${actions[*]}"
  84. }
  85.  
  86. handleerror() {
  87.     code=$1
  88.     (( verbose )) && echo "$self: error $code in $main"
  89.     (( $2 > 1 )) || return 0 # Noting to handle if this is the last file
  90.     case "$action" in
  91.     skip) return 0 ;;
  92.     quit) return 1 ;;
  93.     ask )
  94.         local choice
  95.         read -rp "(Q)uit, (S)kip, or Skip (A)ll ? " choice
  96.         case "$choice" in
  97.         [Aa]*) action="skip" ; return 0 ;;
  98.         [Ss]*) return 0 ;;
  99.             *) return 1 ;; # Educating users not to blindly hit Enter :)
  100.         esac
  101.     esac
  102. }
  103.  
  104. declare -a opts=()
  105. self="${0##*/}"
  106. main="dpkg-deb"
  107. action="ask"
  108. destdir=""
  109. control=1
  110. controldir="DEBIAN"
  111. verbose=0
  112. dverb=0
  113. dquiet=0
  114. code=0
  115. ext="--extract"
  116.  
  117. # Loop options
  118. while (( $# )); do
  119.     case "$1" in
  120.     -h|--help     ) usage                   ;;
  121.     -v|--verbose  ) verbose=1               ;;
  122.     -X|--vextract ) dverb=1                 ;;
  123.     +X            ) dquiet=1                ;;
  124.     -x|--extract  )                         ;; #I'm not so naive.Silently ignore
  125.     --nocontrol   ) control=0               ;;
  126.     --controldir=*) controldir="${1#*=}"    ;;
  127.     --controldir  ) shift ; controldir="$1" ;;
  128.     --destdir=*   ) destdir="${1#*=}"       ;;
  129.     --destdir     ) shift ; destdir="$1"    ;;
  130.     --onerror=*   ) testaction "${1#*=}"    ;;
  131.     --onerror     ) shift ; testaction "$1" ;;
  132.     --            ) shift ; break           ;;
  133.     -*            ) opts+=( "$1" )          ;;
  134.     *             ) break                   ;;
  135.     esac
  136.     shift
  137. done
  138.  
  139. # Basic parser tests
  140. [[ "$controldir" ]] || missing "control directory"
  141.  
  142. # Handle dpkg verbosity (done via extract command)
  143. if ((verbose && !dquiet)) || (( !verbose && dverb )); then ext="--vextract"; fi
  144.  
  145. # Loop file arguments
  146. (( $# )) || missing "file"
  147. while (( $# )); do
  148.     #FIXME: extremely unlikely corner-case flaw: filename without extension, in
  149.     #       a path that contains a dot.  /etc/dir.d/no-deb-ext
  150.     filetitle="${1%.*}"
  151.     if [[ "$destdir" ]] ; then
  152.         path="${destdir}/${filetitle##*/}"
  153.     else
  154.         path="$filetitle"
  155.     fi
  156.     mkdir -p "$path" # make it easy for dpkg
  157.     cmd1=("$main" "${opts[@]}" "$ext"    -- "$1" "${path//\/\///}"            )
  158.     cmd2=("$main" "${opts[@]}" --control -- "$1" "${path//\/\///}/$controldir")
  159.     if (( control )) ; then
  160.         (( verbose )) && echo "$self: executing ${cmd1[@]} && ${cmd2[@]}"
  161.         "${cmd1[@]}" && "${cmd2[@]}" || handleerror $? $# || break
  162.     else
  163.         (( verbose )) && echo "$self: executing ${cmd1[@]}"
  164.         "${cmd1[@]}"                 || handleerror $? $# || break
  165.     fi
  166.     shift
  167. done
  168.  
  169. (( verbose )) && (( code )) &&
  170.     echo "$self: error(s) occurred, exiting with $main last error's code, $code"
  171.  
  172. exit $code
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement