This is the GitHub repo to accompany the Egghead Course "Automate daily development tasks with bash". Watch it on egghead.io.
This repository is structured more as a "cheatsheet" rather than having any runnable code. Click the lesson links to see the code that's covered in each lesson.
Whether it’s for npm install or some git commands, most front-end devs have used bash sometime. Bash has been around awhile (first released in 1989) and it’s proven to be very efficient at automating tasks. Plus, bash is available on every commonly used operating system—it comes with macOS, is the default shell for many Linux distros, and is available on Windows via an emulator or the new Linux subsystem. In this course, we’ll learn the essentials of what every front-end developer should know about bash. The topics we cover will give you confidence in doing things like creating build scripts that run on continuous integration servers or quickly testing and debugging an API with curl
. We’ll go over:
- Interacting with the file system
- Creating, moving, copying, and deleting files and folders
- Finding files and text patterns in files
- Creating and running scripts
- Language syntax like variables and conditionals
Click on a lesson below to jump to the code samples for that lesson.
- Navigate the filesystem in bash
- View files and folders in bash
- Create and Delete Files and Folders in bash
- Move and Copy Files and Folders with bash
- Find Files and Folders with
find
in bash - Search for text with
grep
- Make HTTP requests in bash with
curl
- Create and run bash scripts
- Store and Use Values with bash Variables
- Understand and use functions in bash
- Understand exit statuses in bash
- Use Conditional Statements in bash
- Chain Commands with Pipes and Redirect Output in bash
cd <file path here>
# to go up a directory from your current directory
cd ..
ls
# for more details, add -l (long)
ls -l
# this will output something like this:
# -rw-r--r-- 1 cameronnokes staff 1237 Jun 2 22:46 index.js
# in order, those columns are:
# permissions for you, your group, all
# number of links (hardlinks & softlinks)
# owner user
# owner group
# file size
# last modified time
# file name
# to see hidden files/folders (like .git or .npmignore)
ls -a
# Note, flags can be combined like so
ls -la
cat <file name>
# shows it with line numbers
cat -n <file name>
# view the file without dumping it all onto your screen
less <file name>
# Some useful shortcuts in less
# Shift+g (jump to end)
# g (go back to top)
# / (search)
# q (quit/close)
open <file/folder name>
# view current directory in Finder
open .
# specify an application to use
open <file name> -a TextEdit
touch <file name>
# set the file's contents
echo 'hi' > file.txt
# append to file's contents
echo 'hi' >> file.txt
# note that if you pass a file name that doesn't exist, it'll get created on the fly
mkdir <folder name>
# make intermediary directories as needed
mkdir -p parent/child/grandchild
# Note, this permanently deletes a file
rm <file name>
# Remove a folder and it's contents, recursively
rm -rf <folder name>
mv <target> <destination>
# for example, to rename a file
mv a.js b.js
# move all files in a folder to another folder
mv lib/* src
cp <target> <destination>
# copy everything recursively from one folder to another
cp -R src/* lib
# find all the PNGs in a folder
find <path> -name "*.png"
# find all the JPGs (case insensitive) in a folder
find <path> -iname "*.jpg"
# find only directories
find <path> -type d
# delete all matching files
find <path> -name "*.built.js" -delete
# execute an arbitrary action on each match
# remember `{}` will be replaced with the file name
find <path> -name "*.png" -exec pngquant {} \;
# Basic usage
grep <pattern> <target file or glob>
# Useful flags
# --color (colorizes matches)
# -n (show line numbers)
# -C <number> (show N lines above/below match for context)
# -e (regex search)
The test server is available in the curl-practice-server
directory. Run npm install && npm start
to run it.
curl <url>
# Useful flags
# -i (show response headers only)
# -L (follow redirects)
# -H (header flag)
# -X (set HTTP method)
# -d (request body)
# -o (output to a file)
# to POST JSON
# (technically you don't need -X POST because -d will make it POST automatically, but I like to be explicit)
curl -X POST -H "Content-Type: application/json" -d '{ "title": "Curling" }' http://localhost:3000/api/posts
# POST a url encoded form
curl -X POST --data-urlencode title="Curling again" http://localhost:3000/api/posts
# multiline curl (applies to any bash command)
curl -i -X PUT \
-d '{ "title": "Changed title" }' \
-H "Content-Type: application/json" \
http://localhost:3000/api/posts
# pretty print JSON with jsome
curl https://swapi.co/api/people/1/ | jsome
Here's the jsome package that pretty prints JSON
echo 'echo Hello World' > script.sh
chmod u+x script.sh
./script.sh
The init-js.sh
script for scaffolding a JS project
echo "Initializing JS project at $(pwd)"
git init
npm init -y # create package.json with all the defaults
mkdir src
touch index.js
code .
One way to add that script to your $PATH
:
cp init-js.sh /usr/local/bin/init-js
# no spaces between name, =, and value
var=123
echo $var
# to make it accessible to all child processes of current shell, export it
export var
# this deletes the variable
unset var
To see all environment variables
env
clone-to-temp.sh
script:
temp=$(mktemp -d)
git clone --branch $1 $PWD $temp
echo "branch $1 cloned to $temp"
# run some tasks, tests, etc here
greet() {
echo "$1 world"
}
greeting=$(greet "howdy")
echo "the greeting is $greeting"
global=123
test() {
echo "global = $global"
local local_var="i'm a local"
echo "local_var = $local_var"
}
test
echo "global = $global"
echo "local_var = $local_var" # will be empty because it's out of scope
Get the last run command's exit status
ls
# will be 0 if it ran successfully, 1 - 255 for an error
echo $?
Exit statuses and functions. script.sh
ok() {
return 0
}
fail() {
return 1
}
fail
ok
./script.sh
echo $? # exit status is same as the last run function/command
Basic form
# Some conditional primaries that can be used in the if expression:
# =, != string (in)equality
# -eq, -ne numeric (in)equality
# -lt, -gt less/greater than
# -z check variable is not set
# -e check file/folder exists
if [[ $USER = 'cameronnokes' ]]; then
echo "true"
else
echo "false"
fi
Conditionals can be used inline in a more ternary-like format
[[ $USER = 'cameronnokes' ]] && echo "yes" || echo "no"
check-status.sh
for checking a URL is responding with a 200
check_status() {
local status=$(curl -ILs $1 | head -n 1 | cut -d ' ' -f 2)
if [[ $status -lt 200 ]] || [[ $status -gt 299 ]]; then
echo "$1 failed with a $status"
return 1
else
echo "$1 succeeded with a $status"
fi
}
check_status https://example.org
check_status https://example.org/404
Pipes
# ps ax will list all running processes
ps ax | grep Chrome | less
# get the file size after uglify + gzip
uglifyjs -c -m -- index.js | gzip -9 | wc -c
Redirection
# redirect stdout to a file
ls > ls.txt
# append stdout to a file
echo "hi" >> ls.txt
- You can view a command's documentation right in bash with
man <command name>
. - Official bash manual
- TLDP bash programming intro, basic
- TLDP bash programming intro, advanced