A terminal is the computer application you open (e.g. macOS Terminal, iTerm, etc). You need some kind of terminal app to be able to interact with a shell.
- These are technically called "terminal emulators". They emulate the old-school physical terminals that allowed you to interact with "shell-like" operating systems like MS-DOS.
- More specifically, terminal emulators take your input and forward it to the underlying program (which is generally the shell).
- The terminal is like a car's dashboard while the shell is like the engine.
A shell is the actual program that interprets/processes your input. e.g. zsh, bash, ash, sh, etc. On your MacBook, you are using the zsh shell within the Terminal (or maybe iTerm) application.
- Also known as a command line interpreter/command language interpreter.
- One of the main purposes of a shell is to simply find and execute other programs (e.g. git).
- Shells also provide a built-in programming language (command language) that provides things like control flow, comparison operators, etc.
- So for example there's "bash" the shell program, and "bash" the language.
Further reading: https://unix.stackexchange.com/questions/4126/what-is-the-exact-difference-between-a-terminal-a-shell-a-tty-and-a-con
https://en.wikipedia.org/wiki/POSIX
Simply put, POSIX is a standard created by IEEE that defines what APIs/programs should exist and how they function in order to create a consistent experience across operating systems.
POSIX-certified vs. POSIX-compliant: https://en.wikipedia.org/wiki/POSIX#POSIX-certified
When looking up how to do something in a shell, you'll often see a "POSIX" way of doing it, which means it will most likely work regardless of the OS or shell you're using.
POSIX Shell & Utilities: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/contents.html
POSIX Shell Command Language: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
cat
, less
, and most of the commands you run are programs.
Enter type cat
into your terminal. This will tell you the location of the given program.
Point being, these programs don't just magically exist, they are actual files/programs that you are executing by typing the name of the file.
Shells are just programs too. type zsh
will tell you the location of the zsh file/executable/program.
cd
into the folder that contains cat
(find the folder with type cat
). You should see a bunch of other programs, some of which you will probably recognize.
See what happens if you enter type type
. It should tell you it's a shell built-in.
A shell built-in is a function of a given shell (e.g. zsh). It exists within the zsh program itself.
For example, cd
is also a shell built-in. That means every shell (zsh, bash, etc) technically has its own implementation of cd
.
A "command" is a bit of a misnomer; pretty much anything you run in a command line is either a program or a shell built-in.
cat
is (usually) in the /usr/bin/
directory. This directory is on your path.
Enter echo $PATH
. This is your system's path, which is simply a list of directories.
Any executable within any directory on your path is accessible from anywhere.
You can add directories to your path, so you could have your own bin
directory somewhere and if you wanted executables within that directory to be globally available, all you have to do is add your new bin
directory to the path. (Lots of ways to do this, I recommend you google it.)
So when you enter something into your shell, the shell first checks if it has a built-in function of that name. If not, it iterates through PATH
until it finds a match.
This means the first match found will be executed, so the order of the directories in PATH
can matter.
Most programs have a --help
flag. For example, enter cat --help
. It will tell you how you can use cat
.
Not every program has a --help
flag.
Use man
(short for manual) instead. e.g. man cat
.
man
can sometimes be more comprehensive, but generally --help
and man
will contain the same info.
Further reading: https://seb.jambor.dev/posts/cd-is-not-a-program/ (I highly recommend you read this, it has some really good info.)
You can use the &&
operator.
For example, echo hello && echo goodbye
Anything after the &&
will only run if the previous command ran successfully.
Try running ehco hello && echo goodbye
. (The first echo
is misspelled.)
Whenever a command finishes/exits, it always exits with a status. 0 means the program executed sucessfully. Anything other than 0 is an error.
A non-zero exit status does not necessarily mean the program crashed or anything. A program can choose to emit whatever exit code they want for whatever reason.
You can view the status of the last command that was run by doing echo $STATUS
(or echo $status
on zsh).
Just like in programming, within your shell you can store values (strings) in variables. (Also, shell scripting is programming.)
- In most shells, everything is a string. That is,
echo hello
andecho "hello"
are equivalent. - Variables are case-sensitive.
- Quotes are important in certain situations. That's something we'll cover later.
Create a variable: hello="Hello World!"
You must reference variables with the $
character.
echo $hello
will work. echo hello
will not. (It prints "hello", but not your variable.)
Create a new file called hello.sh
: nano hello.sh
- Generally scripts will end in
.sh
, but file extensions don't matter to the shell and most shell programs. - In this script we implement a flag called
-b
to make it say "Bye" instead.
Arguments to a script can be referenced by number.
- So
$1
refers to the first argument passed in,$2
the second, etc.
arg1=$1
if [ "$arg1" = "-b" ]
then
echo "Bye"
else
echo "Hello"
fi
Try running your script: ./hello.sh
- Remember,
./hello.sh
is saying "look inside the current directory forhello.sh
".hello.sh
is looking for a globally available command namedhello.sh
.
By default, files are not executable.
Make it executable using chmod
: chmod +x hello.sh
chmod
is a program that allows you to change file permissions.+x
allows the file to be executed.
You should be able to run your script now.
The [ "$arg1" = "-b" ]
syntax isn't special.
[
is just a command (usually a shell builtin). It's an alias for test
.
[ "$arg1" = "-b" ]
is equivalent to test "$arg1" = "-b"
.
"$arg1"
is the first argument for [
, =
the second, etc.
if
doesn't have to be used with test
/[
. if
simply looks at the exit status of a command.
For example, you could do something like this:
if cp ./hello.sh ./hello2.sh
then
echo "Copy succeeded"
else
echo "Copy failed"
fi
One line: if cp ./hello.sh ./hello2.sh; then echo "Copy succeeded"; else echo "Copy failed"; fi
A shebang #!
in a script tells your shell what program it should invoke the script with.
For example, if at the top of our script we put #!/bin/bash
, it will run the script with bash.
If there is no shebang, the script will run using the program that executed it.
Create a directory called scripts
: mkdir scripts
Move hello.sh
into scripts
: mv hello.sh scripts
Try running your script.
Your script isn't on path, so your shell can't find it.
Look at your current path: echo $PATH
Add your scripts
directory to path: PATH="/Users/Adam/scripts:$PATH"
- We are setting
PATH
equal to itself and adding our directory.
You should see your directory prepended to path: echo $PATH
Try running your script again.
Changing your path like this is not permanent, it only applies to the current shell session.
If you wanted your scripts
directory to always be on path, you can add the above command to your .zshrc
or equivalent.
Further reading:
How to Add a Directory to PATH in Linux
Add /Applications/IntelliJ IDEA.app/Contents/MacOS
to .zshrc:
path+=('/Applications/IntelliJ IDEA.app/Contents/MacOS')
.zshrc
is a file that runs whenever you start a new zsh shell session.
This file is used for things like setting environment variables, aliases, functions, etc.
Since it's essentially a script that runs once when zsh starts up, any changes to your .zshrc
won't be applied until a new session is started.
OverTheWire - Game to practice command line usage
ssh [email protected] -p 2220
Make sure to logout (exit
) once you're done with a level.
Linux Command Line Cheat Sheet
https://linuxcommand.org/lc3_learning_the_shell.php
https://github.com/ohmyzsh/ohmyzsh - zsh improvements/configs
10 Useful Chaining Operators in Linux with Practical Examples