Skip to main content

🐧 Ubuntu Command Line Interface: A Complete Tutorial

Ubuntu is the Linux distribution most web servers run, and its command line is where backend work actually happens. Deploy a Node app, tail a log at 2 a.m., set file permissions, install a package — all of it flows through the terminal. This reference takes you from the very first prompt to writing your own shell script, one clear command at a time.

Reference & Extra Tutorials · Resources · The Server Environment

🎯 What This Covers

By the end of this reference, you will be able to:

  • Read the shell prompt and understand the command [options] [arguments] structure
  • Navigate the filesystem and manage files with the essential dozen commands
  • Read and change file permissions with chmod and ownership with chown
  • View and search text with cat, less, grep, and find
  • Chain commands with pipes and redirection to build powerful one-liners
  • Install software with apt and write your first executable Bash script

Estimated Time: 60 minutes

Practice: Scaffold a project, set permissions, and write a small backup script.

In This Tutorial

The Shell & the Prompt

When you open a terminal, you're talking to a program called the shell. On Ubuntu that's usually Bash (the Bourne Again SHell). The shell reads what you type, hands the instruction to the operating system, and prints the result. The window it runs in is the terminal; people use "terminal," "shell," and "command line" almost interchangeably.

Open one with Ctrl + Alt + T, or search "Terminal" in the applications menu. On Windows, install WSL (Windows Subsystem for Linux) to get a genuine Ubuntu shell — nearly every backend tool assumes this environment.

Reading the prompt

username@hostname:~$
PartMeaning
usernameThe account you're logged in as
hostnameThe name of the machine
~Your current directory (~ is your home folder)
$A regular user (a # means root/administrator)

When a tutorial shows $ ls, the $ just represents the prompt — you type only ls.

💡 The construction-site analogy

A GUI app is a pre-built house: ready to move into, but you can only change what the builder allowed. The command line is the raw lumber and power tools — steeper to learn, but you can build exactly what you need, and there's no server room on earth without one.

Command Structure

Almost every command follows one shape:

command [options] [arguments]
  • command — the program to run (ls, cp, grep)
  • options — flags that change behavior, prefixed with - or --
  • arguments — what the command acts on (filenames, paths, text)

For example, in ls -la /home: ls is the command, -la are two options combined (long format plus all files), and /home is the directory argument.

📖 The recipe analogy

A command is a recipe. The command is the dish, the options are the preparation notes ("dice finely," "cook slowly"), and the arguments are the ingredients. Same command, different options and arguments, different result.

✅ Two habits that pay off immediately

  • Tab auto-completes file and command names — faster and typo-proof
  • command --help and man command show usage without leaving the terminal (press q to exit man)

Managing Files & Folders

Create: mkdir and touch

mkdir my-project              # one new folder
mkdir docs images styles       # several at once
mkdir -p src/components/ui      # -p builds the whole nested path

touch notes.txt                # create an empty file
touch index.html style.css     # create several

The -p ("parents") flag creates every missing folder in a path instead of failing because a middle folder doesn't exist yet.

Copy & move: cp and mv

cp report.txt backup.txt        # copy a file (original stays)
cp -r templates/ new-project/    # -r copies a whole folder tree

mv report.txt documents/         # move a file into a folder
mv report.txt final.txt          # rename (move to a new name)

mv does double duty: moving and renaming are the same operation — renaming is just "move to the same folder under a new name." The key difference from cp: mv leaves nothing behind, while cp keeps the original.

Delete: rm and rmdir

rm notes.txt                 # delete a file
rm -r old-project/            # -r deletes a folder and its contents
rm -ri old-project/           # -i asks before each deletion (safer)
rmdir empty-folder/           # only removes an EMPTY folder

⚠️ There is no Trash on the command line

rm deletes permanently and immediately — no Recycle Bin, no undo. Read the filename twice before pressing Enter, be careful with wildcards like rm *.log, and never run rm -rf / or paste a destructive command you don't understand. Add -i while you're learning so it asks before each deletion.

Viewing & Searching Text

cat, less, head, tail

cat notes.txt                # print a whole (small) file
less big.log                 # page through a large file (q to quit)
head -n 20 data.csv          # first 20 lines
tail -n 50 app.log           # last 50 lines
tail -f /var/log/syslog      # follow a log live as it grows

tail -f is the one you'll reach for constantly when debugging a running server — it streams new log lines as they appear.

grep — search inside files

grep "ERROR" app.log            # lines containing ERROR
grep -i "error" app.log         # case-insensitive
grep -rn "TODO" src/            # recursive, with line numbers
grep -c "404" access.log        # count matching lines

find — search for files

find . -name "*.js"                    # every .js file below here
find . -type d -name "node_modules"     # directories with that name
find /home -type f -size +100M          # files larger than 100 MB
find . -type f -mtime -7                 # modified in the last 7 days

The . means "start in the current directory," -name matches the filename (quote the wildcard so the shell doesn't expand it first), and -type f/-type d restrict to files or directories.

💡 Quote your wildcards in find

Always write find . -name "*.js" with quotes. Without them, the shell expands *.js before find ever runs, and you get confusing results. The quotes hand the pattern to find untouched.

Permissions & Ownership

Every file has permissions for three groups — the owner, the group, and others — across three actions: read, write, and execute. Run ls -l and you'll see them as a string like -rwxr-xr--.

graph TD A[File permissions] --> B[Owner] A --> C[Group] A --> D[Others] B --> E["Read = 4"] B --> F["Write = 2"] B --> G["Execute = 1"] C --> H["Read + Execute"] D --> I["Read only"]

chmod — change permissions

The numeric ("octal") form adds up read (4), write (2), and execute (1) for each group. So 7 is read+write+execute, 5 is read+execute, 4 is read-only.

chmod +x deploy.sh           # make a script executable
chmod 755 deploy.sh          # rwx for owner, r-x for group and others
chmod 644 config.json        # rw- for owner, r-- for everyone else
chmod -R 755 public/         # apply recursively to a folder
OctalSymbolicTypical use
755rwxr-xr-xScripts and directories
644rw-r--r--Regular files
700rwx------Private, owner-only

chown — change ownership

sudo chown username file.txt            # change the owner
sudo chown username:group file.txt      # change owner and group
sudo chown -R www-data:www-data /var/www # recursive, for web files

⚠️ Don't reach for 777

Setting chmod 777 gives everyone read, write, and execute — a common "just make it work" move that's a genuine security hole. Grant the least permission that does the job: 644 for files, 755 for directories and scripts.

Pipes & Redirection

The real power of the shell is combining small commands. A pipe (|) feeds one command's output into the next; redirection (>, >>) sends output to a file.

Redirection

command > out.txt      # write output to a file (overwrite)
command >> out.txt     # append to a file
command 2> err.txt     # redirect only errors
command > out.txt 2>&1 # both output and errors to one file

Pipes

ls -la | grep ".txt"                 # list, then keep only .txt lines
cat access.log | wc -l               # count lines in a file
du -h | sort -rh | head -10          # ten biggest items, largest first
history | grep git                    # find past git commands
graph LR A[Command 1] -->|output| B[Command 2] B -->|output| C[Command 3] C -->|output| D[File or screen]

📖 The assembly-line analogy

Piping is a factory assembly line. Each command is a station that takes raw material (input), does one job, and passes the result to the next station. A chain of simple stations turns raw data into a finished product — exactly how cat log | grep ERROR | sort | uniq -c turns a messy log into a tidy count of each error.

Packages & Services

apt — install software

Ubuntu manages software with apt. Update the package lists first, then install.

sudo apt update                 # refresh the list of available packages
sudo apt upgrade                # upgrade installed packages
sudo apt install nodejs npm     # install packages
sudo apt remove package-name    # remove a package
apt search keyword              # search for a package

sudo ("superuser do") runs a command with administrative rights — required for anything that changes the system, like installing software.

systemctl — manage services

systemctl status nginx          # is it running?
sudo systemctl start nginx      # start it
sudo systemctl restart nginx    # restart it
sudo systemctl enable nginx     # start automatically at boot

Watching the system

df -h                # disk space, human-readable
du -sh /var/log      # total size of a directory
top                  # live view of processes (q to quit)
ps aux | grep node   # find running node processes

💡 update then install

Always run sudo apt update before installing. It refreshes the catalog of available versions; skipping it can install an outdated package or fail to find a new one.

Your First Shell Script

A shell script is just a file of commands the shell runs top to bottom. It's how you turn a repetitive chore into a single command.

#!/bin/bash
# The first line (the "shebang") tells the system to run this with bash.

echo "Hello, world!"

# Variables — no spaces around the =
name="Ray"
echo "Hello, $name!"

# A conditional
if [ "$name" = "Ray" ]; then
    echo "Welcome back, Ray."
else
    echo "Who goes there?"
fi

# A loop
for i in 1 2 3; do
    echo "Count: $i"
done

Make it executable, then run it:

chmod +x hello.sh    # give it execute permission
./hello.sh           # run it (the ./ means "in this directory")

A useful example: a timestamped backup

#!/bin/bash
# Back up a folder into a timestamped tar.gz archive.

source_dir="$HOME/documents"
backup_dir="$HOME/backups"
timestamp=$(date +%Y%m%d_%H%M%S)      # command substitution

mkdir -p "$backup_dir"
tar -czf "$backup_dir/backup_$timestamp.tar.gz" "$source_dir"

echo "Backup created: $backup_dir/backup_$timestamp.tar.gz"

The $(date ...) is command substitution: the shell runs date and drops its output right into the string. Quoting variables like "$source_dir" keeps paths with spaces from breaking.

Output

$ ./backup.sh
Backup created: /home/username/backups/backup_20260731_142530.tar.gz

Command Cheat Sheet

Keep this within reach — these cover the vast majority of daily terminal work.

CommandWhat it doesExample
pwdPrint working directorypwd
lsList contentsls -lh
cdChange directorycd ../src
mkdirMake a directorymkdir -p a/b/c
touchCreate an empty filetouch app.js
cpCopycp -r src/ dist/
mvMove or renamemv a.txt b.txt
rmDelete (permanent!)rm -r build/
catPrint a filecat notes.txt
lessPage through a fileless big.log
grepSearch inside filesgrep -rn TODO src/
findSearch for filesfind . -name "*.js"
chmodChange permissionschmod +x run.sh
sudoRun as administratorsudo apt update
aptManage packagesapt install nodejs

Practice & Quiz

🏋️ Exercise 1: Scaffold and secure a project

Goal: From your home directory, build this tree, then make the script executable and confirm the layout:

my-app/
├── index.js
├── run.sh
└── src/
    └── utils.js
💡 Hint

Use mkdir -p for the nested folder, touch for the files, chmod +x for the script, and ls -R to verify.

✅ Solution
cd ~
mkdir -p my-app/src
cd my-app
touch index.js run.sh src/utils.js
chmod +x run.sh

# Verify
ls -R
# .:
# index.js  run.sh  src
# ./src:
# utils.js

🏋️ Exercise 2: Count errors in a log

Goal: In a file app.log, count how many lines contain the word ERROR, case-insensitively, using a pipe.

✅ Solution
grep -i "error" app.log | wc -l
# or, equivalently, grep's own counter:
grep -ic "error" app.log

🎯 Quick Quiz

Question 1: Which command permanently deletes a folder and everything inside it?

Question 2: What does the | (pipe) do?

Question 3: What does chmod 755 run.sh grant?

Best Practices & Pitfalls

✅ Do

  • Use Tab completion constantly — it's faster and prevents typos
  • Run pwd and ls to orient yourself before any destructive command
  • Quote paths that contain spaces: cd "My Folder"
  • Run sudo apt update before installing packages
  • Grant the least permission that works — 644 for files, 755 for scripts
  • Read command --help before running anything unfamiliar

❌ Don't

  • Run rm -rf on a path you haven't double-checked — there is no undo
  • Paste commands from the internet without understanding them
  • Reach for chmod 777 or sudo to "just make it work"
  • Forget that Ubuntu is case-sensitive — App.jsapp.js
  • Assume wildcards are harmless — preview rm *.log with ls *.log first

⚠️ The wildcard trap

# Intended: delete temp files
rm temp *.log
# Oops — the stray space means "delete a file named temp
# AND every .log file." The shell expands wildcards BEFORE rm runs.

Before any destructive wildcard, run the same pattern through ls first to see exactly what it will match.

Summary

🎉 Key Takeaways

  • The shell reads command [options] [arguments] — and Tab plus --help are your best friends
  • pwd, ls, and cd orient and move you through a single case-sensitive tree rooted at /
  • mkdir, touch, cp, mv, and rm create and manage files — and rm deletes permanently
  • chmod and chown control access; grant the least permission that works
  • Pipes and redirection chain small commands into powerful one-liners, and a few lines of Bash automate the rest

📚 Additional Resources

🚀 What's Next?

You've reached the end of the Reference & Extras track. Everything backend in this bootcamp — Git, Node, npm, Docker, and your deploys — runs on the command line you just learned. Head back to the Course Home to keep building on this foundation.

🎉 You command the terminal now!

This is the environment your servers live in. Every tool in the stack sits on top of these commands — you've just learned the ground floor of the whole building.