├── README.md ├── showing-file-download-progress-using-wget └── demo.sh └── showing-progress-with-a-bash-spinner ├── README.md └── demo.sh /README.md: -------------------------------------------------------------------------------- 1 | Bash Tips and Tricks 2 | ==================== 3 | 4 | An archive of the tips and tricks I share on my blog. 5 | -------------------------------------------------------------------------------- /showing-file-download-progress-using-wget/demo.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | download() 4 | { 5 | local url=$1 6 | echo -n " " 7 | wget --progress=dot $url 2>&1 | \ 8 | grep --line-buffered "%" | \ 9 | sed -u -e "s,\.,,g" | \ 10 | awk '{printf("\b\b\b\b%4s", $2)}' 11 | echo -ne "\b\b\b\b" 12 | echo " DONE" 13 | } 14 | 15 | file="patch-2.6.37.gz" 16 | echo -n "Downloading $file:" 17 | download "http://www.kernel.org/pub/linux/kernel/v2.6/$file" 18 | -------------------------------------------------------------------------------- /showing-progress-with-a-bash-spinner/README.md: -------------------------------------------------------------------------------- 1 | I've [mentioned before][wget] that I like to show users of my scripts useful 2 | information. This can be a complex progress bar, a simple progress meter, or 3 | it can be an animation to let the user know the script hasn't hung. These 4 | animations are typically called [Throbbers][throbber] are exist purely to tell 5 | the user to continue patiently waiting. Sometimes folks, like met, call 6 | Throbbers Spinners for two reasons. First, a very common throbber animation 7 | type is the spinning wheel. Second, the word throbber sounds oddly sexual, and 8 | sort of creeps me out if I say it too many times in a sentence (Just kidding. 9 | Well, no, not really.) 10 | 11 | This tip will show you to create a spinner for your Bash scripts. If you have 12 | a long running process and don't want to try to tell the user approximately 13 | how much of that process is left to run, showing them a spinner is a great 14 | alternative. 15 | 16 | ### Implementing the Spinner 17 | 18 | The throbber, er I mean spinner, is implemented as a loop that shifts a string 19 | during each iteration. 20 | 21 | spinner() 22 | { 23 | local pid=$1 24 | local delay=0.75 25 | local spinstr='|/-\' 26 | echo "$pid" > "/tmp/.spinner.pid" 27 | while [ "$(ps a | awk '{print $1}' | grep $pid)" ]; do 28 | local temp=${spinstr#?} 29 | printf " [%c] " "$spinstr" 30 | local spinstr=$temp${spinstr%"$temp"} 31 | sleep $delay 32 | printf "\b\b\b\b\b\b" 33 | done 34 | printf " \b\b\b\b" 35 | } 36 | 37 | Let's examine the meat of the tip. First, I remove the first character from 38 | the string and save the remaining characters into a `temp`. 39 | 40 | local temp=${spinstr#?} 41 | 42 | Then I use `printf` to output the first character of `spinstr`, which contains 43 | our animation. 44 | 45 | printf " [%c] " "$spinstr" 46 | 47 | Finally, I shift `spinstr` by constructing a new string that contains the 48 | value of `temp` and all characters from `spinstr` that aren't in `temp`. 49 | 50 | local spinstr=$temp${spinstr%"$temp"} 51 | 52 | ![Bash Spinner Steps 1 and 2][step12] 53 | ![Bash Spinner Steps 1 and 2][step34] 54 | 55 | ### How it Works 56 | 57 | When you have a task to run that will take a large (or unknown) amount of time 58 | invoke it in a background subshell like this: 59 | 60 | (a_long_running_task) & 61 | 62 | Then, immediately following that invocation, call the spinner and pass it the 63 | PID of the subshell you invoked. 64 | 65 | spinner $! 66 | 67 | The `$!` is a [bash internal variable][internal-variable] for the PID of the 68 | last job run in the background. In this case, it will give us the PID of the 69 | bash shell executing our long running task. 70 | 71 | 72 | ### An Example 73 | 74 | 75 | [internal-variable]: http://tldp.org/LDP/abs/html/internalvariables.html "Bash Internal Variables" 76 | [wget]: /showing-file-download-progress-using-wget.html "Showing File Download Progress using Wget" 77 | [throbber]: http://en.wikipedia.org/wiki/Throbber "Throbbers" 78 | ![step12]: /wp-content/uploads/2011/02/bash-spinner-step12.png "Bash Spinner Steps 1 and 2" 79 | ![step34]: /wp-content/uploads/2011/02/bash-spinner-step34.png "Bash Spinner Steps 3 and 4" 80 | -------------------------------------------------------------------------------- /showing-progress-with-a-bash-spinner/demo.sh: -------------------------------------------------------------------------------- 1 | spinner() 2 | { 3 | local pid=$1 4 | local delay=0.75 5 | local spinstr='|/-\' 6 | while [ "$(ps a | awk '{print $1}' | grep $pid)" ]; do 7 | local temp=${spinstr#?} 8 | printf " [%c] " "$spinstr" 9 | local spinstr=$temp${spinstr%"$temp"} 10 | sleep $delay 11 | printf "\b\b\b\b\b\b" 12 | done 13 | printf " \b\b\b\b" 14 | } 15 | 16 | (sleep 10) & 17 | echo -n "Doing something really important, please wait... " 18 | spinner $! 19 | echo " DONE" 20 | --------------------------------------------------------------------------------