NodeSchool Cleveland

September 19, 2016

Learn You Bash

Thanks to our sponsors

Before We Begin

Slides: http://bit.ly/nsclepresentations

1. Install Node.js

>= 4.0.0 (>= 5.1.0 for Windows)

2. Install Bash

Mac/Linux: You already have it
Windows:

3. Install workshopper


$ npm install -g learnyoubash
                                    
pizza2

Tonight's workshopper...

learnyoubash

Why Bash?

1. Why not?

Save time
Prevent mistakes
Document processes

2. Because it is used

3. It is commonly available

The Basics

Packaged as textual source code

The .bash extension is typical

Made executable by typical means…

  1. Shebang line:
    
                                        #!/usr/bin/env bash
                                        
  2. Make the file executable:
    
                                        chmod +x my-file.bash
                                        

If we're going to do this...

let's get serious!


#!/usr/bin/env bash

# file: create-bash.bash
#
# This script creates a new Bash script file.
# It inserts the shebang line and sets the file to be executable.
#
# Arguments:
# $1 The name of the file (typically has .bash extension)
#
printf '#!/usr/bin/env bash\n\necho "hello world"' > $1
chmod +x $1
                    

This workshopper will teach you…

  • Variables
  • Arrays
  • Shell expansions
  • Streams
  • Pipes
  • Lists of commands
  • Conditionals
  • Loops
  • Functions
  • Debugging

Interactive Mode

Command Description
history Shows a numbered list of the most recent commands
!! Expands with the last command
Example: sudo !!
!<num> Expands with the last command
!str Expands with the last command starting with str
!?str? Expands with the last command containing str
^orig^repl^ Re-executes the last command with orig replaced with repl
ctrl-r Incrementally search backwards through history

Variable Gotchas

Variables are preceded with $ when they are read, but not when assigned


language="Bash"
echo "Make $language great again."
                    

Also, spaces cannot be placed around the assignment operator (=).

Multiple Commands on a line

Multiple commands must be separated by ";"


if [[ … ]]
then
    …
fi
                            

if [[ … ]]; then
    …
fi
                            

You can also string commands together using boolean operators && and ||

cmd1 && cmd2 && cmd3 Execute commands until one fails
cmd1 || cmd2 || cmd3 Execute commands until one succeeds

Expansion and Substitution

(…) Subshell
Contains commands that are run in a subprocess.
Will not affect the parent process.

x=2; (x=4); echo "$x"  # prints 2
                                        
$(…) Command substitution
Same as using `…` (backticks)
The output of executing the command is used as part of outer command

echo "Hello, $(whoami)"
                                        
{ …; } Parse grouping
How we normally think of parenthesis.
Requires spaces around the braces and a closing semicolon.

x=2;{ x=4; }; echo "$x"   # prints 4
                                        

Expansion and Substitution

${VAR} Parameter expansion
Similar to $VAR but with possible transformations

  • Default values
  • Indirect variables
  • More

A=${A:-hello}
                                    
((…)) Arithmetic instruction
A computation on integers with syntax familiar to other programming languages.
Used primarily in assignments and conditionals.

(( n += 1 ))  # Increment.
                                    
$((…)) Arithmetic expression
Just expands the expression

z=$((z+3))
                                    

Expansion and Substitution

[[ … ]] Test expression
You need a space inside and outside each bracket
You need spaces around all operators

if [[ "$varA" == 1 && ("$varB" == "t1" || "$varC" == "t2") ]]; then
    ⋮
fi
                                        
Numeric operators
-eq, -ne
-lt, -le
-gt, -ge
String operators
==, !=,
-z null (zero length)
-n not null
Filesystem operators
-e exists
-f file exists
-d directory exists
-h symbolic link exists
-s not 0 size
-r, -w, -x

When using == and !=, the right side is a pattern. [[ "$foo" == a* ]] tests if $foo starts with "a" while [[ "$foo" == "a*" ]] tests if $foo is exactly "a*".

Always use double quotes around variable substitutions. If you don't, your script will not handle variables that contain whitespace or \[*? characters well.

Other topics to explore

Customizing your prompt (PS1)
Commonly used environment variables
  • PATH
  • EDITOR
  • PS1, PS2, PS3, PS4
  • PROMPT_COMMAND
Aliases
Command line completion
Commands

Resources

This presentation: http://nodeschoolcle.github.io/presentations/

bash-handbook

A great Stack Overflow answer about expansions and substitutions

Always use double quotes around variable substitutions and command substitutions: "$foo", "$(foo)"

Demystify test, [, [[, ((, and if-then-else

Online Bash shell (Complete with mock filesystem)

Thank You!

Please register for meetups you are interested in, so we can prioritize them.

Slide Template

subtitle


var a = 1;
var b = 1;
var c = 1;