diff --git a/bash.pdf b/bash.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..322ffe69b9329623d848e14fdfd8695525b26d29
Binary files /dev/null and b/bash.pdf differ
diff --git a/bash.txt b/bash.txt
index d9a3335f682992a09b0a414ce41776f6d051b418..9ee29e104fe3efc0e6878b891d5ce8919f33f1d3 100644
--- a/bash.txt
+++ b/bash.txt
@@ -53,6 +53,27 @@ Now try:
 The braces give us considerable more control, and some extra features,
 as we'll see.
 
+It is also possible to set variables for a single command. There
+are two ways to do this:
+
+    /usr/bin/env a=foo my_command
+    a=foo my_command
+
+Both of these set the variable `a` to the value `foo`, but *only*
+for the environment seen by `my_command`. This is used frequently
+to override default variables without changing them:
+
+    JAVA_HOME=${HOME}/my_java some_java_program
+    LD_LIBRARY_PATH=${HOME}/build/lib my_c_program
+
+By convention, script-local variables are lowercase, and more global
+variables (like HOME) are uppercase.
+
+Subprocesses typically don't get passed the variables you define. To
+change this, you need to export the variable:
+
+    export PATH
+
 
 Parameter Expansion
 -------------------
@@ -71,6 +92,16 @@ details and other expansion options.
 |             | If *s* not provided, remove the pattern             |
 |             | # and % perform prefix and suffix matches           |
 
+We can use this in a script along with variable overriding for handling
+script inputs symbolically, rather than positionally:
+
+    ${target:=foo.txt}
+    grep foobar ${target}
+
+We would call this (assuming it's called "myscript"):
+
+    target=/etc/hosts myscript
+
 
 Quoting
 -------
@@ -99,16 +130,50 @@ Command Execution
 
 There are multiple ways to do this. Consider an executable `foo`:
 
-| *Invocation* | *Effect*                                               |
-| ------------ | --------                                               |
-| `foo`        | foo is run as a subprocess normally                    |
-| `foo &`      | foo is run in the background, as execution continues   |
-| `` `foo` ``  | foo is run as a subprocess, and its STDOUT is returned |
-| `$(foo)`     | Same as the above                                      |
+| *Invocation* | *Effect*                                                 |
+| ------------ | --------                                                 |
+| `foo`        | foo is run as a subprocess normally                      |
+| `foo &`      | foo is run in the background, as execution continues     |
+| `. foo`      | foo is run *in the current shell*                        |
+| `(foo)`      | a subshell is started, and foo is run as a subproc of it |
+| `` `foo` ``  | foo is run as a subprocess, and its STDOUT is returned   |
+| `$(foo)`     | Same as the above                                        |
 
 The last two are equivalent, but the $() form is preferable, because
 it is clearer and can be nested.
 
+The dot-execution is useful for snippets of bash code which set
+environment variables or define functions. Think of it like an
+"include" statement.
+
+The advantage of running in a subshell is that it doesn't impact
+the current shell. Here's an example:
+
+    for d in *  # "*" expands to the contents of the current directory
+    do
+        if [ -d $d ]  # Test that $d is a directory
+        then
+            (cd $d; git pull origin master)
+        fi
+    done
+
+If we ran in the parent shell, we would have to make this longer:
+
+    cwd=$(pwd)
+    for d in *  # "*" expands to the contents of the current directory
+    do
+        if [ -d $d ]  # Test that $d is a directory
+        then
+            cd $d
+            git pull origin master
+            cd $cwd
+        fi
+    done
+
+We could use `..` instead of `$cwd`, but then we'd have to worry
+about `cd $d` failing. With a subshell, we don't need to worry about
+this at all.
+
 
 Working with Positional Parameters
 ----------------------------------
@@ -346,3 +411,104 @@ Let's combine this for command-line argument parsing:
 Functions
 ---------
 
+Defining a function:
+
+    function my_func {
+        local a=$1
+        echo $a
+    }
+
+Functions begin with the `function` keyword, then a name, and then
+the body of the function, in curled braces. The `local` keywords
+defines a variable in the function's scope. If not used, the variable
+will be defined in the global scope, and hence visible outside of
+the function. Positional parameters are redefined for the function's
+scope.
+
+Once defined, the function behaves like any other command:
+
+    my_func "hello"
+
+You can define particularly useful functions in your ~/.bashrc,
+which will be executed (using .) whenever you start a new shell.
+
+
+Aliases
+-------
+
+Common one-liners are often nice to put into simple aliases, which
+are defined like:
+
+    alias ls='ls -FC'
+
+Here are some aliases I find useful:
+
+    alias ls='ls -FC'
+    alias la='ls -A'
+    alias ll='ls -l'
+    alias ltr='ls -ltr'
+    alias lsd='ls -lsd'
+
+These are defined in my ~/.bashrc. There's also a file called either
+~/.bash_profile or ~/.profile, which is only run for a login shell
+(that is, only once when you first log in). When you modify one of
+these files, make sure you re-dot them
+
+    . ~/.bashrc
+    . ~/.bash_profile
+    . ~/.profile
+
+
+Scripting
+---------
+
+Some principles I live by:
+
+ 1. If I'm going to do something more than once, I script it.
+ 2. If I do something once, there's a good chance I'm going to have
+    to do it again.
+
+Most shells, bash included, treat executable text files specially.
+Given no other information, they run them as scripts for the current
+shell. *Do not assume that file extensions mean anything.* At the
+very least, bash does not care about the name of your file, it only
+cares about the content. Naming a file `foo.py` does not mean bash
+will treat it as a python file, for instance.
+
+To run the script correctly, there's an easy way and a hard way.
+The hard way is to call the appropriate interpreter explicitly:
+
+    bash my_shell_script.sh
+    python my_python_script.py
+
+The easy way is to use a convention called *shebang* (short for
+"hash-bang"). The shell will look at the first line of an executable
+ASCII file. If that line begins with a shebang, the arguments to
+that provide the program with which to run the script:
+
+    #! /bin/bash
+
+You can even provide options:
+
+    #! /bin/bash -x
+
+For python, there's a better way to call it:
+
+    #! /usr/bin/env python
+
+What does this do? We're not actually invoking python directly.
+Instead, we invoke env, which passes the parent environment. In
+particular, this means it's also using the parent shell's $PATH
+variable to determine how to find python. This has a couple of
+advantages:
+
+ * The location of python may vary from installation to installation,
+   but env's location is always predictable.
+ * If you use python virtual environments, this will pick up your
+   virtualenv python.
+
+As a final note, make sure your scripts are executable! See "chmod"
+in the filesystems quick-ref for details, but 99 times out of 100,
+you will want to run `chmod a+x` on your script. git keeps track
+of file permissions in addition to the contents.
+