Table of contents
- Terminal
- BASH (The bourne-again shell)
- Bash vs ZSH vs Fish
- Why Linux? So why Linux over other operating systems?
- Anatomy of CLI command
- File system
- Tips and tricks with warp
- Common terminal commands for web devs
- VIM
- Interacting with files
- Wildcards and Replacements
- Streams and pipes
- Users,Groups and permissions
- Environments (CLI)
- Package management
Throughout my career, I've worked with developers who purposefully avoid the command line, and I think that's a shame. You can do a lot of things quickly with just a bit of know-how.
Terminal
The terminal is a text-based interface to interact with the computer's operating system. It allows users to type commands and receive text-based feedback.
Terminals can be found on various operating systems, like Linux, macOS, and even Windows (Command Prompt or PowerShell).
In the context of Linux and macOS, the default terminal emulator is often used to run a shell, like Bash.
My favourite terminal:
BASH (The bourne-again shell)
A command-language interpreter for interacting with a computer from the command line. When you open up a terminal on a UNIX machine like macOS or Linux, the default shell is usually BASH, where you can type a command
This command will later be interpreted by a shell and executed on the operating system. Is it like any other application that lives in the binaries directory?
Where can I find it?
cd /
(root of the application)
cd ~ (Users)
Bash vs ZSH vs Fish
Zsh (Z Shell) and Bash (Bourne Again Shell) are both Unix-like command shells that provide a command-line interface and scripting capabilities. Here are some key differences between Zsh and Bash:
Bash: It is the default shell on most Unix-based systems, including macOS and many Linux distributions. Bash has been around for a long time and is widely used. It has a rich set of features and syntax, making it powerful for scripting and automation tasks.
Zsh: Zsh is known for having additional features and a more interactive user interface compared to Bash. It includes features like advanced tab completion, spelling correction, and improved customization options.
Why Linux? So why Linux over other operating systems?
First, it's free. Anyone can use Linux to do anything without paying anyone a dime. This is useful for college students who don't have any money, but it's also critical for large businesses running thousands or tens of thousands of servers. It can save them millions of dollars to not have to pay for an operating system.
Anatomy of CLI command
What you're looking at is often called a REPL, or Read, Evaluate, Print Loop. It's basically an interactive way of programming where you're writing one line of code at a time, feeding data in and out of little programs. Using the commands here, you can navigate around your computer, read and write data, make network calls, and do all sorts of other stuff. Basically, anything you can do with a desktop, you can do with a command line; it's just a little less obvious how to do it.
The way a REPL works is that you send one command at a time, and the shell runs the command and returns to you a result.
File system
The way bash works is that you are always in a folder somewhere on your computer. Think of it like your computer's File Explorer or Finder: you can navigate into and out of folders while you look for files.
Our first command we're going to run on your computer ispwd
. So typepwd
and hit enter. This will send the command pwd
to the shell which will evaluate that and print out the answer.
pwd
is a little program that tells you the current path of where you are in the file system. pwd
stands for the present working directory. It's basically like asking the computer "where am I right now?" Mine says /Users/vincenguyen
This is what paths look like, /<outermost folder name>/<a nest folder>/<a yet more nest folder>
. The /
represents a level of nesting inside of another folder. The root directory is at /
.
So by typing pwd, we've successfully run our first program! Congrats!
Help
I forget all the time how to use various different programs. pwd
is very simple but others are way more complex. For most programs, you can add --help
at the end and it'll usually spit out some brief instructions on how to use the program. This one isn't super necessary right now, but go ahead and type pwd --help
to see its help text. --help
is called a flag. We'll talk more about those later.
man ls
You can open the terminal manual pages for any command with
the man command
Flag
Navigating
cd (go to where?)
cd/ (root)
The root directory is at the top of the directory structure. All other directories and files reside under it. No directory exists "above" the root.
Other important directories, such as
/bin
,/home
,/usr
, and/etc
, are direct subdirectories of the root.
cd ~
In Unix-like systems, each user has their own home directory, and it is usually represented by the tilde (~
). For example, if your username is "john," your home directory might be something like /Users/vincenguyen depending on the specific operating system
.ls (list files or folders)
When you simply use ls
without any options, it provides a basic listing of non-hidden files and directories in the current directory. The output typically includes just the names of the files and directories.
We can put more options into it
ls
:
-l
provides a long listing format with detailed information about files and directories. However, it does not display hidden files.-a
This option shows hidden files and directories, but it doesn't provide detailed information like the-l
option (all)
ls -la
will give you a detailed listing of all files and directories, including hidden
The permission of the file?
Who made it?
The group that users belong to?
What is the size of the file in bytes?
When was it last modified?
What is the name of the folder?
Ls acts as a find file in regular expressions
Tips and tricks with warp
There is so much guidance in warp that we can actually study our key combinations right in warp
Press tab for auto-completion
Keyboard tricks
Only two types of delete (D and back-space)
Combo | Meaning |
Ctrl + A (A = 65 beginning ) | Beginning of the line |
Ctrl + E (end) | The end of the line |
Ctrl + F (forward) | Move cursor forward one character |
Ctrl + B (backward) | Move cursor backward one character |
Ctrl + D (delete) | Delete one character |
Ctrl + K (kill) | Kill text from the current cursor to the end |
Ctrl + U (kill) | Kill the line |
Alt + Arrow left | Jump to left of each keyword |
Alt + Arrow right | Jump to right of each keyword |
Alt + backspace | Delete from the current cursor to the end |
Alt + Delete | Delete from the current cursor to the right |
Reverse Search
Instead of having to hit up a bunch of times to find a command you ran forever ago (it keeps track of something like the past 10K commands you've run), you can CTRL+R to do a reverse search (reverse meaning starting with the most recent and working background to most recent.)
Let's say I ran the commandecho "hello my friends"
last week and I wanted to find that command again, and I only remember that it had something to do with "friends". I'd type CTRL+R and start typing "friends.". If it was the most recent command that I had run with "friends" in it, it'd show up, and I could hit enter, and it'd run. If there was another command between now and again, I could hit CTRL+R again to look further back in history. This is also super useful and something I do a lot.
!!
If you type !!
in bash, it will replace the !!
with whatever the last command you ran. So if you just type !!
and enter, it'll run the last command you ran. If you run sudo !!
it'll re-run the same command again but with sudo
in front (we'll talk about sudo soon.)
Copy and paste on the CLI
- Be careful of what you copy and paste. If you copy something off a website, using JavaScript they can switch what you highlight with something more nefarious so that when you paste it, it doesn't do what you copied. So I could have copied,
echo "this is harmless"
but it actually pastessend_attacker_my_passwords
. Be careful that you trust where you're copying and pasting from (StackOverflow is fine!)
Opening files just by clicking through a warp
Open an external terminal from VS code
Command + Shift + C
New tab
Command + T (tab)
Workflow with wrap
Control + Shift + R
Create your own workflow
You can execute a workflow in several ways:
From Warp Drive, click the workflow
From the Command Palette
CMD-P
, search for a workflow you’d like to execute, click or select and enterFrom Command Search
CTRL-R
, search for a workflow you'd like to execute, click or select and enter.When a workflow is selected, you can use
SHIFT-TAB
to cycle through the arguments.
Command Inspector
You can simply hover your mouse over the command
Common Terminal Interface Commands
Cmd + t : Open a new terminal tab
Cmd + w : Close current terminal tab
Cmd + d : Open horizontal terminal tab
Cmd + shitf + d : Open vertical split terminal tab
Common terminal commands for web devs
I suggest you check out this wonderful blog
https://chrispennington.blog/blog/introduction-to-terminal-commands/
VIM
I am not a command-line text editor and never have been. I made one shot in 2013-ish to try to switch to Vim and ended up broken and confused. However, as a newly-minted CLI affiliate, it's important that you know how to do the most basic sorts of text editing in a CLI since you can't always open things outside of the CLI, and sometimes the CLI will toss you into a text editor, and you need to know how to get done what you need to get done.
Command modes
:q quit
:q! force quit and not saving
:w write
:wq write and quit
Interacting with files
Cat (concatenate)
It doesn't paginate or anything fancy; it just reads it and outputs it to the standard output
cat package.json
Head/tail
These two are very descriptive. Head will read the first lines of a file and output them, and Tail will read the last lines of a file and output them. By default, both will output 10 lines, but you can adjust that.
mkdir (make-directory)
mkdir makes a new directory/folder. Run mkdir my-new-folder
to see a new folder. Run cd my-new-folder
to change the directory into it.
Another useful thing is the -p
(for parents) flag. Run mkdir -p a/lot/of/folders
and it will create all those folders as necessary.
touch
Touch create a new, empty file. If I say touch new-file.txt
it'll create a new file called new-file.txt right where I am. If new-file.txt already exists then it just changes the last modified and last accessed time. This can be useful in a variety of scripting contexts where changing a file's modified time signals that something is supposed to happen. Most of the time I just use it to create new files.
rm
Remove a file! Be very careful; this program has got no chill. You tell it to delete everything, and it will oblige you.
If you sayrm new-file.txt
it will remove one file,. If you sayrm my-new-folder
it won't let you,. You have to sayrm -r my-new-folder
to remove a directory. If my-new-folder has anything in it, it's going to make you confirm every single file that you want to delete. If you're removing a very full file, this can get tedios, so you can add-f
to force everything through without confirmation.
Again, exercise huge caution here; thisrm -rf
is a bell that you can't unring. Once something has been rm
'd, it doesn't go to the trash; it's just gone.
Never run this command: rm -rf /
. This is a famous command to run that will start deleting your whole system, including the critical system files. It will start deleting everything until it deletes something so critical that the system will never recover. I tell you, so you're extra cautious to never do it.
cp (copy)
If you are inside the example
folder and want to copy test.txt
to the parent directory, use:
cp test.txt ..
If you want to copy test.txt
to a specific directory outside the current one, use:
cp test.txt /path/to/target/directory/
Outside 3 levels (just like import and export in JS)
cp test.txt ../../../backup/
mv (move)
mv stands for move. This how you move a file from one place to another, or how you rename a file (which is still moving it in some sense.) Try running touch file.txt
then mv file.txt new-name.txt
.
Unlike cp, with mv you don't have to do anything special to move a folder. Just do mv folder-name new-folder-name
and it all works
Wildcards and Replacements
Wildcards
Let's say you wanted to remove all the .txt files in your directory. You could say rm file1.txt file2.txt file3.txt <etc>
but that's time consuming. You know they all end with .txt, wouldn't it be nice if you could say "remove anything that ends in .txt"? You can! That's what the wildcard *
is for with paths. Instead of the command above, you can do rm *.txt
and it'll remove everything matches that pattern. If you want to try this, use the -i
flag so it'll prompt if you want to delete the files or not so you don't accidentally things you don't mean to.
Okay, so say you wanted to match file1.txt and file2.txt but not file.txt. file*.txt
will match all three of those. For that you can use ?
. So try file?.txt
.
Try this
touch file1.txt file2.txt file.txt
ls file*.txt
ls file?.txt
Finally you can use [] to limit your characters too. Let's say you
wanted 1-5. So you could say ls file[1-5].txt. Or you can say anything
that matches not these characters by saying ls file[^1-5].txt
Expansions
touch file{4,5,6}.txt
touch {Aisha,Lanie,Joumana,Krista}-profile.txt
touch file{0..10}.txt
Streams and pipes
Linux has an interesting concept where basically all input and output (which are text) are actually streams of data or text. Like plumbing pipes, where you can connect and disconnect sections to redirect water to different places, so too can you connect and disconnect streams of data.
The standard stream
There are three standard streams: stdin (said standard input or standard in), stdout (said standard output or standard out), and stderr (said standard error or standard err.) stdin is an input stream to a program, and the other two are output streams. stdout for all non-error text, the normal output. stderr is just for error information.
stdout
Replacing vs appending
ls -lsah 1> ls.txt (replacing)
ls -lsah 1>> ls.txt (appeding)
stderr
Redirect Standard Output and Standard Error to One File
ls -l /bin/usr > ls-output.txt 2>&1
Alternative way
ls -l /bin/usr &> ls-ouput.txt
ls -l /bin/usr &>> ls-output.txt
// appending either information or error to ls-output.txt
Ignore error from terminal
ls -ls /bin/user > ls-output.txt 2> /dev/null
Stdin
Pipes
The ability of commands to read data from standard input and send to standard output is utilized by a shell feature called pipelines. Using the pipe operator | (vertical bar), the standard output of one command can be piped into the standard input of another.
command1 | command2
ls -l /usr/bin | less
Filters
Pipelines are often used to perform complex operations on data. It is possible to put several commands together into a pipeline. Frequently, the commands used this way are referred to as filters. Filters take input, change it somehow, and then output it. The first one we will try is sorting
ls /bin /usr/bin | sort
uniq—Report or Omit Repeated Lines
The uniq command is often used in conjunction with sort. uniq accepts a sorted list of data from either standard input or a single filename argument (see the uniq man page for details) and, by default, removes any duplicates from the list
ls /bin /usr/bin | sort | uniq
If we want to see the list of duplicated items, we can
ls /bin /usr/bin | sort | uniq -d
wc-Print line, Word, and Byte Counts
wc ls-output.txt
7902 64566 503634
number of lines
words
bytes
grep-Print lines matching a pattern
grep is a powerful program used to find text patterns within files
ls /bin /usr/bin | sort | uniq | grep zip
ls /bin /usr/bin | sort | uniq | grep zip -i (ignore senstive)
ls /bin /usr/bin | sort | uniq | grep zip -v (print parts don't
match the pattern)
head/tail—Print First/Last Part of Files
ls /bin /usr/bin | sort | uniq | grep zip -i | head -n 5]
Users,Groups and permissions
Linux is inherently a multi-user system. You have an account (in our case, ubuntu is the name of the user by default for Multipass) but there are always multiple users on a Linux system. Many of the users of the system aren't even meant to be actual human users; many programs will create their own users and groups to keep themselves separate from userspace.
User's account on the system
cat /etc/passwd
This file is a system file that stores information about user accounts on the system. Each line in the file represents a user account and contains various pieces of information, such as the username, user ID (UID), group ID (GID), home directory, shell, and more.
User
Superuser
superuser is the user can create another users and do things that the other users can not do
sudo (super user do) su (switch user) to (by default, its a root) means that use super power to switch my current user to super user (root)
Warning
What we did, sudo su
is usually not what you want to do. When you do things as root, it usually means that only root in the future will be able to modify and delete files it makes. It also means that if you fat-finger a command and accidentally type something wrong, you really can burn down the house. It's like using a flamethrower to start a grill: you can do it, but there's a good chance you're taking the house down with you.
Sudo
Sudo is one-time use; if we want to do something that requires special permission, like adding new users, we can do this
sudo useradd vincenguyen2
sudo passwd vincenguyen2
su vincenguyen2
Groups
Just like we can add and subtract permissions from a user in Linux, we can actually do it for whole cohorts of users using groups. This is useful for many reasons. Let's say you have a server that everyone connects to get documents. You could have one cohort of users that just needs to read / download the documents. In this case, we could make a readers
group and give them read-only permission to all files. They'll never need to (or be able to) create new files. Now, if a hacker gets ahold of their credentials, they can only read files and not wreck your server. And when we add a new user, we just add them to the readers
group and that's it! If we need to later modify it so that readers
can add files to just one directory, we can easily make that happen by adding write permissions to one directory for the readers. See how this can streamline things?
su vincenguyen2
sudo usermod -aG sudo vincenguyen2 (add vincenguyen2 to sudo group)
sudo whoami (now vincenguyen2 can use sudo command)
Permissions
The first character
Attribute | File type |
- | A regular file |
d | A directory |
l | A symbolic link. The remaning attributes is always rwxrwxrwx are dummy values. The real value are those of the file pointing to |
... | To be more |
The others (12 characters)
Attributes | Files | Folder |
r (read) | Allows a file to be opened and read | It allows a folder's contents to be listed if the execute attribute is also set |
w (write) | This attribute allows a file to be written or truncated; however, this attribute does not allow files to be renamed or deleted | Allows file within this folder to be created, deleted, and renamed if the execute attribute is also set |
x (execute) | Allows a file to be treated as a program and executed. | Allows a folder to be entered |
Chmod
user(u) | The owner of a file(who created a file) |
group(g) | Any member of the file within a group |
other(o) | Any one else |
So chmod allows you to directly change the permissions of the file rather just changing the owners. So instead saying "now ubuntu can write to this folder insetad of brian" we can say "any person in this ground can read from it" or "everyone on this computer can read from it". Let's do a few examples.
sudo index.js; // use root to create index.js
ls -l index.js;
-rw-r--r-- 1 vincenguyen staff 0 Jan 19 09:51 index.js
(only root can read and write)
whoami; //Vince
echo "Hello I can't write to this file" > index.js; Permissions denied
chmod -u="rwe",-g="rw",-o="rw" index.js > allows groups and others
echo "Hello I can write to this file now" > index.js
Shortcut
sudo chmod 777 index.js;
sudo chmod 640 index.js;
One last one you'll see is the use of +
and -
. If you want to make a file executable, you can say chmod +x secret.txt
and it'll add executable to each of the permissions. As you may imagine chmod -x secret.txt
takes it away. You can use it with w and r too, just that's not super common to do.
Environments (CLI)
Whether or not you realize it, your current session of your shell has a bunch of variables set. Most are just set by the OS, some by Multipass (or whatever you're using to run your computer), some by various programs, and some by you.
Go ahead and run printenv
to see what variable have been set.
Some of the most common variables that we use
/ is the root of our computers
echo $SHELL; /bin/zsh
echo $HOME; /Users/vincenguyen cd $HOME
echo $USER; vincenguyen
echo $PATH;
: /Users/vincenguyen/.nvm/versions/node/v16.19.0/bin
:/opt/homebrew/bin:/opt/homebrew/sbin
:/usr/local/bin:/System/Cryptexes/App/usr/bin
:/usr/bin
:/bin
:/usr/sbin
:/sbin
:/usr/local/share/dotnet
:~/.dotnet/tools
which node;
/Users/vincenguyen/.nvm/versions/node/v16.19.0/bin/node
Path variables (accessible program)
On Unix-like systems, if you have a program called "example" in the directory "/usr/local/bin" and "/usr/local/bin" is included in the PATH variable, you can run the "example" command from any terminal without specifying the full path.
Managing the PATH variable allows users to execute commands or run programs from any location on the system without having to specify the full path to the executable every time. It's a convenient way to make commonly used executables easily accessible.
node -v
If you don't install node.exe on your machine, you'll get this error
bash: node: command not found
Shebang
#!/usr/bin/env node
console.log("Hello world");
When you run this script from the command line (e.g., node script.js
), the operating system sees the shebang line and understands that it needs to use the node
interpreter to execute the script.
The env
command is used to locate the node
executable in the user's PATH, making the script more portable.
The script content is then interpreted and executed by the Node.js runtime.
Package management
Package management is a method of installing and maintaining software on a system
Package Files
A package may consist of numerous programs and data files that support the programs (think of its as our modules)
Repositories
Packages are made available to the users of a distribution in central repositories, which may contain many thousands of packages, each specially built and maintained for the distribution (think of its as npm)
Dependencies
If a package requires a shared resource, such as a shared library, it is said to have a dependency. Modern package management systems all provide some method of dependency resolution to ensure that when a package is installed, all of its dependencies are installed too (think of it as a package. json)
Common Package Management Tasks
Installing a package from a repository