These are my notes from the MIT's The Missing Semester of Your CS Education.
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:
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 📝
-
$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.
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 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/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
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$IFS
character (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$1
to$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!
Nice overview!