GreenRaccoon23

adb-pull

Jul 29th, 2015
2,043
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 7.71 KB | None | 0 0
  1. #!/bin/bash
  2. shopt -s extglob
  3.  
  4. # Print help and exit.
  5. _help() {
  6.     local path="$0";
  7.     local script=${path##*/};
  8.     cat << EOH >&2
  9. ${script}
  10.   Run `adb pull` and verify the integrity of the pulled files.
  11.   Usage:
  12.       ${script} "<files/directories>..."
  13. EOH
  14.     local status="${1}";
  15.     if ! [ "${status}" ]; then
  16.         status=0;
  17.     fi;
  18.     exit "${status}";
  19. }
  20.  
  21. # Analyze user arguments.
  22. _getopts() {
  23.     if (($# == 0)); then
  24.         _help 1;
  25.     fi;
  26.    
  27.     # Declare bool options.
  28.     #local -a Bools=(
  29.     #    ""
  30.     #);
  31.  
  32.     # Iterate over user arguments.
  33.     local -i i;
  34.     local flag;
  35.     for ((i=1;i<=$#;i++)); do
  36.         eval flag="\$$i";
  37.         case "${flag}" in
  38.             *(-)[hH] | *(-)[hH][eE][lL][pP] )
  39.                 _help 0;
  40.                 ;;
  41.         esac;
  42.     done;
  43.  
  44.     # Set bool options.
  45.     #="${Bools[0]}"
  46. }
  47.  
  48. # Set console font color.
  49. # Optionally, print messages and then reset the confole font.
  50. #   (Use as a replacement for `echo`.)
  51. _c() {
  52.     # Unset color first
  53.     #   (in order to skip running `_u` if the console font is currently bold).
  54.     _u;
  55.     if (($# == 0)); then
  56.         return;
  57.     fi;
  58.    
  59.     local -A Codes=(
  60.         ["black"]=0
  61.         ["red"]=1
  62.         ["green"]=2
  63.         ["yellow"]=3
  64.         ["blue"]=4
  65.         ["magenta"]=5
  66.         ["cyan"]=6
  67.         ["white"]=7
  68.     );
  69.     local k code;
  70.     for k in "${!Codes[@]}"; do
  71.         if [[ "${k}" != "${1}" ]]; then
  72.             continue;
  73.         fi;
  74.         code="${Codes[$k]}";
  75.     done;
  76.  
  77.     # Quit if $1 wasn't one of the 8 colors.
  78.     if ! [ "${code}" ]; then
  79.         return 1;
  80.     fi;
  81.     # Set font color.
  82.     tput setaf "${code}";
  83.  
  84.     # If any messages were passed,
  85.     #   print them and then reset the console font color.
  86.     if (($# == 1)); then
  87.         return;
  88.     fi;
  89.     _echecho "${@:2}";
  90.     _u;
  91. }
  92.  
  93. # Set console font to bold.
  94. # Optionally, set the console font color as well,
  95. # If any other arguments are passed,
  96. #   print them and then reset the confole font.
  97. #     (Use as a replacement for `echo`.)
  98. _C() {
  99.     # Set then
  100.     if (($# > 0)); then
  101.         _c "${1}";
  102.     fi;
  103.  
  104.     tput bold;
  105.  
  106.     if (($# < 2)); then
  107.         return;
  108.     fi;
  109.     _echecho "${@:2}";
  110.     _u;
  111. }
  112.  
  113. # Restore the default console font settings.
  114. _u() {
  115.     tput sgr0;
  116. }
  117.  
  118. # Echo each value in an array individually.
  119. _echecho() {
  120.     local message;
  121.     for message; do
  122.         echo "${message}";
  123.     done;
  124. }
  125.  
  126. # Echo a command, and then evaluate it.
  127. _evalcho() {
  128.     echo "$@";
  129.     eval "$@";
  130. }
  131.  
  132. # Remove an extension from a filename.
  133. _rmExt() {
  134.     local file="${1}";
  135.     local ext="${2}";
  136.     if [[ "${file:$((${#file}-1)):1}" == "." ]]; then
  137.         file="$(_rmExt "${file}" "")";
  138.     fi;
  139.  
  140.     if [[ "${file%\.${ext}*}" != "${file}" ]]; then
  141.         echo "${file%\.${ext}*}";
  142.     else
  143.         echo "${file%${ext}*}";
  144.     fi;
  145. }
  146.  
  147. # Back up a file if it exists.
  148. _bak() {
  149.     local file="${1}";
  150.     if ! [ -e "${file}" ] || [ -e "${file}.bak" ]; then
  151.         return 0;
  152.     fi;
  153.  
  154.     _evalcho mv "${file}" "${file}.bak";
  155. }
  156.  
  157. # Create a tar archive of the file to pull [if it is a directory].
  158. _tar() {
  159.     echo "adb shell \"cd \"${PARENT_DIR}\" && tar -cf \"${BASE}.tar\" \"${BASE}\"\"";
  160.     adb shell "cd \"${PARENT_DIR}\" && tar -cf \"${BASE}.tar\" \"${BASE}\"";
  161.  
  162.     local valid;
  163.     valid="$(adb shell "if tar -xOf \"${FILE}.tar\" &>/dev/null; then printf 0; fi")";
  164.     if [[ "${valid}" != 0 ]]; then
  165.         _tar;
  166.     fi;
  167. }
  168.  
  169. # Extract the pulled tar archive.
  170. _untar() {
  171.     _bak "${BASE}";
  172.     _evalcho adb shell rm "${FILE}";
  173.     _evalcho "tar -xf \"${COPY}\"" &&
  174.         rm "${COPY}";
  175. }
  176.  
  177. # Wait for Android device to connect.
  178. _connect() {
  179.     local connected;
  180.     connected="$(adb devices | head -2 | tail -1)";
  181.     if [ "${connected}" ]; then
  182.         return 0;
  183.     fi;
  184.  
  185.     echo "Waiting for Android device to connect...";
  186.     adb wait-for-device &&
  187.         echo "  Android device connected.";
  188. }
  189.  
  190. # Verify whether the remote file exists.
  191. _exists() {
  192.     local exists;
  193.     exists="$(adb shell "if [ -e \"${FILE}\" ]; then printf 0; fi")";
  194.     if [[ "${exists}" == 0 ]]; then
  195.         return 0;
  196.     fi;
  197.     return 1;
  198. }
  199.  
  200. # Run `adb pull` to copy the file from the Android device.
  201. _pull() {
  202.     _bak "${COPY}";
  203.     _evalcho adb pull -p -a "${FILE}" "${COPY}";
  204. }
  205.  
  206. # Verify whether the md5sum of the pulled file matches that of the original.
  207. _verify() {
  208.     if ! [ -e "${COPY}" ]; then
  209.         return 1;
  210.     fi;
  211.  
  212.     local md5File;
  213.     md5File="$(adb shell md5sum "${FILE}")";
  214.     echo "${md5File}";
  215.     md5File="${md5File%  *}";
  216.  
  217.     local md5Copy;
  218.     md5Copy="$(md5sum "${COPY}")";
  219.     echo "${md5Copy}";
  220.     md5Copy="${md5Copy%  *}";
  221.  
  222.     if [[ "${md5File}" == "${md5Copy}" ]]; then
  223.         return 0;
  224.     fi;
  225.     return 1;
  226. }
  227.  
  228. # Rerun script.
  229. _retry() {
  230.     if (($# == 0)); then
  231.         _retry "Failed to pull \"${FILE}\". Retrying...";
  232.         return $?;
  233.     fi;
  234.  
  235.     _c red "$@";
  236.     if [ -e "${COPY}" ]; then
  237.         rm -r "${COPY}";
  238.     fi;
  239.     $0 "${FILE}";
  240. }
  241.  
  242. # Run main function.
  243. _main() {
  244.     # Print in green the name of the target file in order to serve as a title.
  245.     #   (This makes the output easier to read when pulling multiple files.)
  246.     _c green "${FILE}";
  247.  
  248.     # Wait for Android device to connect.
  249.     _connect;
  250.  
  251.     # If the target file does not exist on the Android device, quit.
  252.     if ! _exists; then
  253.         _c red "${FILE} doesn't exist.";
  254.         return 1;
  255.     fi;
  256.  
  257.     # Tar the target file if it is a directory
  258.     #   in order to check its md5sum later.
  259.     if [ "${DO_TAR}" ]; then
  260.         _tar &&
  261.             FILE="${FILE}.tar" &&
  262.             COPY="${COPY}.tar";
  263.     fi;
  264.  
  265.     # Run `adb pull`.
  266.     _pull;
  267.     if (($? != 0)); then
  268.         _retry "Failed to pull \"${FILE}\". Retrying...";
  269.         return $?;
  270.     fi;
  271.  
  272.     # Compare the md5sum of the pulled file with that of the original one.
  273.     # If they do not match, remove the pulled file and rerun this script.
  274.     _verify;
  275.     if (($? != 0)); then
  276.         _retry "${FILE} transferred incorrectly." "  Re-pulling \"${FILE}\"...";
  277.         return $?;
  278.     fi;
  279.    
  280.     # If the remote file was tarred earlier,
  281.     #   remove the temporary tar file on the Android device
  282.     #   and untar the pulled one.
  283.     if [ "${DO_TAR}" ]; then
  284.         _untar &&
  285.             FILE="$(_rmExt "${FILE}" "tar")" &&
  286.             COPY="$(_rmExt "${COPY}" "tar")";
  287.     fi;
  288.  
  289.     echo "Successfully pulled \"${FILE}\".";
  290.  
  291.     # Make the final line of this script's output
  292.     #   the name of the new/pulled file.
  293.     echo "${COPY}";
  294. }
  295.  
  296. # Check if user requested help.
  297. _getopts "$@";
  298.  
  299. # Declare the name of the target file to be pulled.
  300. declare FILE="${1}";
  301.  
  302. # Give the pulled/local file the basename of the file on the Android device.
  303. declare BASE;
  304. BASE="$(basename "${FILE}")";
  305. declare COPY="${BASE}";
  306.  
  307. # If the name of the requested file does not begin with '/',
  308. #   guess the path of the target file.
  309. if [[ "$(printf '%c' "${FILE}")" != "/" ]]; then
  310.     if [[ "${FILE}" == "sdcard" ]]; then
  311.         FILE="/sdcard";
  312.     elif [[ "${FILE}" == "${BASE}" ]]; then
  313.         FILE="/sdcard/${FILE}";
  314.     else
  315.         FILE="/${FILE}";
  316.     fi;
  317. fi;
  318.  
  319. # If the target file is a directory,
  320. #   prepare to tar it in order to read an md5sum later.
  321. declare IS_DIR;
  322. IS_DIR="$(adb shell "if [ -d \"${FILE}\" ]; then printf 0; fi")";
  323. if [[ "${IS_DIR}" == 0 ]]; then
  324.     declare DO_TAR=0;
  325.     declare PARENT_DIR;
  326.     PARENT_DIR="$(dirname "${FILE}")";
  327. fi;
  328.  
  329. # Start the main function.
  330. _main;
  331.  
  332. # Loop through this script for any other files the user requested.
  333. if (($# > 1)); then
  334.     $0 "${@:2}";
  335. fi;
  336.  
  337. exit $?;
Advertisement
Add Comment
Please, Sign In to add comment