Shell tools and scripting — missing semester notes
Published: 2020-11-21 15:50:17

These are my notes from the MIT's [The Missing Semester of Your CS Education](https://missing.csail.mit.edu/). 

*** 

# Lecture 2: Shell Tools and Scripting

## Echo and interpolation 🤖
- `echo` will take as many arguments as you want and will treat each space as a beginning of new argument; for that reason, you can pass arguments as: 
  - `echo Hello World` (which will introduce new lines)
  - `echo Hello\World` (one line)
  - `echo "Hello World"` (one line)
  - `echo 'Hello World'` (one line)
- declaring variables happens with no spaces: `name=Sylwia`; you invoke the variable with a dollar sign: `$name`
- you can interpolate the value of the variable with double quotes:
```bash
  name=Sylwia
  echo $name #Sylwia
  echo "My name is $name" #My name is Sylwia
  echo 'My name is $name' #My name is $name
```
- you can save an output of a command to a variable, e.g.:
```bash
  date=$(date)
  echo "today is $date" # today is Fri Nov 20 13:34:55 EST 2020
```

## Variables 📝
- `$0` stands for the name of the script
- `$#` - number of arguments passed in
- `$$` - pid (process id) of this command
- `$1` (up to `$9`) - the first (ninth) element in a collection
- `$@` - all the arguments
- `$?` — error code from the previous command, e.g.
```bash
echo "Hello" #Hello
$? #0 because everything went well
mkdir test
!! #mkdir test; mkdir: test: File exists
echo $? #1
true 
echo $? #0 because true always evaluates to no errors
false 
echo $? #1
```
- `$_` — last argument of the previous command
- `!!` — repeats the last command (e.g. `sudo !!` will pass the last command as an argument to sudo)

## Logical operators 🤓
- `||` — it prints the left-hand side if it's true, otherwise, the right-hand side will print; 
- `&&` — it prints if both sides are true;
- `;` - will print no matter what
- `-ne` - comparison operator (non-equal)

## Searching and finding 👀
- `ls *.sh` - an example of *globbing*; lists any file that has this combination of letters
- `ls ?.sh` - looks for any file that has just one character before the .sh
- `ls -R` will list all the files recursively
- `find . -name src -type d` - recursively find in the current folder a file with a name of "src" and the type of "directory"
- `find . -path '**/test/*.py' -type f` - find in the current folder all the files that are in any `/test` subfolder located in any subfolder
- `find . -mtime -1` finds all the files that have been modified in the last day
- `find . -name "*.tmp" -exec rm {} \;` - find all files with the `.tmp` ending execute removal
- `fd . -name "*.tmp"` - uses regex for looking for files and ignores git files
- 🚨 `grep -R foobar .` - looks for examples of foobar in all the files in this directory
- `ripgrep` - same but nicely-formatted and you can get a few lines of context

## History 📙
- `ctrl + r` - reverse search
- `history` — shows all command history
- `history 1` - shows last command
- `history 100 | grep ls` - shows all commands in the last 100 command history entries that contained "ls"

## Misc 🧀
- `convert image.{png,jpg}` - same as `convert image.png image.jpg`
- `touch foo{,1,2,3}` will create 4 files (foo, foo1, etc.)
- `touch project{1,2}/main/foo{,1,2}` will create 6 files (3 in each path)
- `touch {foo,bar}/{a..j}` will create a to j files in both dirs
- `#!/usr/local/python` gives the shell path to execute a command in another language; you could achieve the same with `#!/usr/bin/env python` (if you don't know where it lives)
- `shellcheck` is a debugging tool for scripting; it takes an argument of a file

***
Cover photo by energepic.com from [Pexels](pexels.com)