These are my notes from the MIT's The Missing Semester of Your CS Education.
Lecture 2: Shell Tools and Scripting
Echo and interpolation 🤖
-
echowill 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:
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.:
date=$(date)
echo "today is $date" # today is Fri Nov 20 13:34:55 EST 2020
Variables 📝
-
$0stands 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.
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 -Rwill 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/testsubfolder located in any subfolder -
find . -mtime -1finds all the files that have been modified in the last day -
find . -name "*.tmp" -exec rm {} \;- find all files with the.tmpending 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 asconvert 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/pythongives 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) -
shellcheckis a debugging tool for scripting; it takes an argument of a file
Cover photo by energepic.com from Pexels
Top comments (4)
Awesome write-up! I’ve been knee deep in bash’s positional parameters all week.
To add to this already thorough list,
$*creates one combined argument separated by the$IFScharacter (default is a space), while$@acts like an array of each individual argument (which, as you mention, can be isolated further by accessing them in order from$1to$9, but also beyond that by adding braces${10}, ${11} ...).For example (taken from here):
Would print the following with multiple arguments:
So if you’re trying to iterate over arguments individually, use
$@, whereas if you’re trying to do something with the group of arguments as a single whole, use$*.Ohhhh, this is super interesting and helpful. Thank you for taking the time to write the comment and for sharing the link - I’m going to check it out!
My pleasure! Bash can be really obtuse sometimes, but it's a powerful command language, and you can especially do a lot with these positional parameter arguments depending on how you set up your scripts. Happy hacking!