Bash for JS's developers

How to use command-line like a pro

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.


  • 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

$SHELL is a variables that created by the OS system for us

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:

  1. 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.

  2. 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!


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



cd (go to where?)

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 :

  • -lprovides a long listing format with detailed information about files and directories. However, it does not display hidden files.

  • -aThis 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?

we have many argument that you can pass into the function ls such as -r (meaning reverse listing every file nested inside a folder)

Ls acts as a find file in regular expressions

In VS Code, we can use regular expressions to search through the entire project. How can we do that with ls?

Tips and tricks with warp

Sorry but this is my favourite terminal for OS and I want you to use it too

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

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 leftJump to left of each keyword
Alt + Arrow rightJump to right of each keyword
Alt + backspaceDelete from the current cursor to the end
Alt + DeleteDelete 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

  1. 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

Command + 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 enter

  • From 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.

  • More on

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


I am not a command-line text editor person 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


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.

-f flag with head and tail: whenever the file updates, it will update in real-time

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 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.


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.

remove {{fileName}} -rf (recursive and force) :(

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)

cp is short for copy and does just that. If you want to copy a file, you runcp source-file.txt destination-file.txt. You can also cp a file into a directory and implicitly keep the name of the original file by saying cp source-file.txt my-new-folder/ and you'll have a file called source-file.txt inside of my-new-folder (the trailing slash is optional; I just wanted to make sure you understood my-new-folder is a directory.)

If you want to copy a whole folder and everything in it, use cp -R source-directory destination-directory to recursively copy everything from one place to another.

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


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


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.


Instead of going to the screen, it output into a file

Replacing vs appending

ls -lsah 1> ls.txt (replacing)
ls -lsah 1>> ls.txt (appeding)


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



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


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

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.



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)


It's a best practice that we don't switch to superuser.

What we did, sudo suis 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.


Best practice if we really want to do something one time as a root user(super user) then it's fine to do it once :) (better than sudo su)

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
macOS doesn't have the same unix commands as Linux. This command only works on Linux :(


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 readersgroup 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)
It's considered best practice to not use super-user. We should separate non-user for daily tasks and only use superusers when necessary.


The first character

AttributeFile type
-A regular file
dA directory
lA 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)

r (read)Allows a file to be opened and readIt 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 deletedAllows 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


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


4 2 1 is a decimal to binary math (2^2,2^1,2^0)
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.


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.

These variables has already been set my the OS

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
Note that all of the PATH variable is located at the root(system) /
which 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


#!/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 envcommand is used to locate the nodeexecutable 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)


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)


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

That's it forks; there will be a second part of it :)