[[unix]] [[cli]] [[shell]]
# Bash
## Reference
- [Bash-Oneliners](https://github.com/onceupon/Bash-Oneliner)
- [Bash conditional expressions](https://www.gnu.org/software/bash/manual/html_node/Bash-Conditional-Expressions.html)
- [Pattern Matching](https://www.gnu.org/software/bash/manual/html_node/Pattern-Matching.html)
- [Shell Parameter Expansion](https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html)
- [Shell Tools and Scripting (MIT missing-semester)](https://missing.csail.mit.edu/2020/shell-tools/)
- [pure sh bible](https://github.com/dylanaraps/pure-sh-bible)
- [shellcheck](https://www.shellcheck.net/) - bash linter
### Special Vars
| | |
| ---------------- | ------------------------------------------------------------------------------------------------------ |
| `$0` | name of the shell or shell script |
| `$1`, `$2`, `$3` | [positional parameters](https://www.gnu.org/software/bash/manual/html_node/Positional-Parameters.html) |
| `"$@"` | an array-like representation of positional parameters: `{$1, $2, $3 ...}` |
| `"$*"` | the IFS expansion of positional parameters, `$1 $2 $3 ...` |
| `$#` | count of positional parameters |
| `$-` | current shell options |
| `$_` | most recent parameter |
| `$IFS` | (input) field separator |
| `$` | current shell PID (not sub-shell) |
| `$?` | most recent pipeline exit status |
| `$!` | most recent background PID |
| | |
- [special parameters](https://www.gnu.org/software/bash/manual/html_node/Special-Parameters.html)
- [shell variables](https://www.gnu.org/software/bash/manual/html_node/Shell-Variables.html)
### Config Files
| file | order | use | execution | notes |
| ----------------- | ----- | ---------------------------- | ----------------------------------- | ---------------------------------------------------------------------------------- |
| `/etc/profile` | 0 | login shell | if exists | |
| `~/.bash_profile` | 1 | login shell | if exists, skips other config files | commands that should execute 1x, conditionally sources `~/.profile` or `~/.bashrc` |
| `~/.bash_login` | 2 | login shell | if exists, skips other config files | |
| `~/.profile` | 3 | login shell | if exists | |
| `~/.bashrc` | | interactive, non-login shell | | executed on every shell launch |
#### Managing `dotfiles`
- <https://dotfiles.github.io>
##### With [just a git alias](https://fwuensche.medium.com/how-to-manage-your-dotfiles-with-git-f7aeed8adf8b)
```bash
git init --bare $HOME/.dotfiles
# put this in .bashrc
alias dotfiles='/usr/bin/git --git-dir=$HOME/.dotfiles/ --work-tree=$HOME'
# tell git to hide untracked files
dotfiles config --local status.showUntrackedFiles no
dotfiles status
dotfiles add .vimrc
dotfiles commit -m "Add vimrc"
dotfiles add .bashrc
dotfiles commit -m "Add bashrc"
dotfiles push
```
##### With [chezmoi](https://dev.to/jerrynsh/a-brief-guide-to-manage-dotfiles-1h59)
/ʃeɪ mwa/ (shay-moi)
- [user guide](https://www.chezmoi.io/user-guide/command-overview/)
- <https://github.com/pmbauer/dotfiles>
```bash
# pull changes and apply in a single command
chezmoi update
# pull changes and see what would change
chezmoi git pull -- --rebase && chezmoi diff
# apply changes in ~/.local/share/chezmoi
chezmoi apply
# install on new machine with single command
# note: setup ssh keys first if your dotfiles repo is private
# note: populate ~/.config/chezmoi/chezmoi.toml first for templates
$ sh -c "$(curl -fsLS https://chezmoi.io/get)" -- init --apply $GITHUB_USERNAME
```
## Cookbook
### strict mode
```bash
#!/usr/bin/env bash
set -euo pipefail
IFS=