Navigate a Project with the Shell
Introduction
This is the first lesson of the version-control chapter, aligned with course 3 of the Meta Front-End Developer pathway ("Version Control"). Before you can use Git, you need to be comfortable in the place where Git lives: the command line. Professional front-end work depends on it. You install packages with npm, start a development server with npm run dev, run Jest tests, and drive Git, and all of these happen in a terminal. The terminal is not a relic. It is faster, scriptable, and identical on almost every machine, which makes it the shared language of development teams.
By the end of this lesson you will be able to move around a project, create and inspect files and folders, read and search text, chain commands together, and understand how the shell finds programs and handles permissions. The practice scenario is original: you are joining the Harbor Workshops team and must set up the project folder, find where a bug is mentioned, and prepare the repository for the Git lessons that follow.
Learning objectives
- Explain the roles of the terminal, the shell, and the file system, and read a path correctly.
- Navigate with
pwd,ls, andcd, using absolute paths, relative paths,.,.., and~. - Create, copy, move, and delete files and folders with
mkdir,touch,cp,mv, andrm, and know which operations cannot be undone. - Read and search files with
cat,less,head,tail, andgrep. - Combine commands with pipes and redirection.
- Describe environment variables,
PATH, and file permissions at the level needed to diagnose common errors. - Use tab completion, history, and
--helpormanto work faster and learn commands on your own. - Prepare a project folder with a
.gitignore,README.md, andpackage.jsonready for version control.
1. Terminal, shell, and file system
Three terms are often mixed up.
- The terminal (or terminal emulator) is the window that displays text and takes keyboard input.
- The shell is the program running inside the terminal that reads your commands and runs them. Common shells are bash, zsh (the default on current macOS), and PowerShell on Windows. Windows users can also use Git Bash or the Windows Subsystem for Linux (WSL), which give a bash-style shell. This lesson uses bash/zsh syntax.
- The file system is the tree of folders and files on disk.
A command has a name, optional flags (also called options), and arguments:
ls -l src
# ls -> command
# -l -> flag (long listing)
# src -> argument (what to list)
Short flags use one dash (-l) and can often be combined (-la). Long flags use two dashes (--all). The prompt (often ending in $ or %) tells you the shell is waiting for a command.
Paths
Everything on disk has a path. An absolute path starts at the root of the file system (/ on macOS and Linux) and works from anywhere:
/Users/amira/projects/harbor-workshops/src/App.jsx
A relative path starts from your current working directory:
src/App.jsx
Special names make relative paths short:
| Symbol | Meaning | Example |
|---|---|---|
. |
The current directory | ./script.sh |
.. |
The parent directory | cd .. |
~ |
Your home directory | cd ~/projects |
/ |
The root (when leading) or a separator | /usr/bin |
On macOS and Linux paths are case-sensitive: App.jsx and app.jsx can be two different files. Windows is usually case-insensitive, which is one reason a project that works on one machine can fail on another. Treat names as case-sensitive always.
2. Moving around
Three commands cover most navigation.
pwd # print working directory
# /Users/amira
ls # list the current folder
# Desktop Documents projects
ls -la projects # long format, including hidden files
cd projects # change directory
cd harbor-workshops
pwd
# /Users/amira/projects/harbor-workshops
cd .. # up one level
cd - # back to the previous directory
cd # with no argument: go home
Files whose names start with a dot, such as .git, .gitignore, and .env, are hidden by default. ls -a (all) shows them. You will see .git in the next lesson: it is the hidden folder where Git stores all history.
A name containing spaces must be quoted or escaped, otherwise the shell treats it as two arguments:
cd "My Projects" # quoted
cd My\ Projects # escaped
The simplest habit is to avoid spaces in project folder names and use kebab-case instead (harbor-workshops).
Speed tools
- Tab completion: type the first letters of a name and press Tab. The shell completes it or lists the possibilities. It saves typing and prevents typos.
- History: press the Up arrow to recall previous commands, or Ctrl+R to search them.
- Clear the screen:
clearor Ctrl+L. - Stop a running command: Ctrl+C. This is how you stop a development server.
3. Creating, copying, moving, and deleting
mkdir harbor-workshops # create a folder
cd harbor-workshops
mkdir -p src/components # -p creates parent folders as needed
touch README.md src/App.jsx # create empty files (or update timestamps)
cp README.md README.backup.md # copy a file
cp -r src src-copy # copy a folder (-r = recursive)
mv README.backup.md docs.md # rename (move within the same folder)
mv docs.md src/ # move into a folder
rm src/docs.md # delete a file
rm -r src-copy # delete a folder and its contents
Two cautions deserve emphasis.
rmhas no recycle bin. A deleted file is gone, and it is not in the system trash.rm -rf(recursive, force) deletes a whole tree without asking. A typo such asrm -rf ~ /tmp(note the space) can be catastrophic. Before deleting, runlson the same path to confirm what you are about to remove. Files that Git already tracks can be recovered from history, which is one reason to commit early.mvandcpoverwrite silently.mv a.txt b.txtreplacesb.txtif it exists. Use-i(interactive) to be asked first:cp -i,mv -i,rm -i.
mv is also the rename command. There is no separate rename in the basic toolkit.
4. Reading and searching text
cat package.json # print a whole file
less src/App.jsx # scroll a long file (q to quit, / to search)
head -n 5 src/App.jsx # first five lines
tail -n 20 server.log # last twenty lines
tail -f server.log # follow new lines as they are written
wc -l src/App.jsx # count lines
grep searches text for a pattern. It is the tool you will use most often to answer "where is this used?".
grep "bookSeats" src/App.jsx # lines containing bookSeats in one file
grep -r "bookSeats" src # search recursively through a folder
grep -rn "bookSeats" src # -n adds line numbers
grep -ri "capacity" src # -i ignores case
grep -rl "TODO" src # -l lists only file names
grep -rn "TODO" --exclude-dir=node_modules .
Always exclude node_modules (or run the search inside src): it contains thousands of files and drowns real results.
find searches for files by name rather than content:
find src -name "*.test.js" # every Jest test file
find . -name "*.jsx" -not -path "./node_modules/*"
The * is a wildcard (glob) expanded by the shell, so ls src/*.jsx lists all .jsx files directly under src.
5. Pipes and redirection
Each program has three standard streams: input (stdin), output (stdout), and error (stderr). The shell lets you connect them.
>writes output to a file, overwriting it.>>appends output to a file.<reads input from a file.|(the pipe) sends one command's output to the next command's input.2>redirects error output.
ls src > files.txt # save the listing (overwrites files.txt)
echo "node_modules" >> .gitignore # append a line
grep -rn "TODO" src | wc -l # how many TODOs are there?
ls -l | grep ".md" # show only Markdown files
npm test 2> errors.log # keep only error messages in a file
npm run build > build.log 2>&1 # both streams into one file
Pipes are why small commands are so powerful: each does one job, and you combine them. The shell also lets you chain commands with && (run the next only if the previous succeeded) and ; (run the next regardless):
npm run build && npm run preview # preview only if the build succeeded
The exit status of the last command is stored in $? (0 means success; anything else means failure). && relies on that status.
6. Environment, PATH, and permissions
Environment variables
An environment variable is a named value available to programs started from the shell.
echo $HOME # /Users/amira
echo $SHELL # /bin/zsh
export API_URL="http://localhost:4000" # set for this session and child programs
printenv API_URL
Front-end tools read variables for configuration. Vite exposes variables prefixed with VITE_ to your browser code, loaded from .env files; never put secrets in anything that ships to the browser, because the browser bundle is public. Keep .env files out of Git.
PATH
When you type node, the shell does not search the whole disk. It looks through the folders listed in the PATH variable, in order, and runs the first match.
echo $PATH
# /usr/local/bin:/usr/bin:/bin:/Users/amira/.nvm/...
which node # shows which executable would run
node --version
The error command not found: npm almost always means the program is not installed or its folder is not in PATH. which and echo $PATH are the first two diagnostics. Version managers such as nvm work by changing PATH so that the chosen Node version is found first.
Permissions
On macOS and Linux each file has permissions for the owner, group, and others: read (r), write (w), and execute (x).
ls -l deploy.sh
# -rw-r--r-- 1 amira staff 210 Oct 16 09:00 deploy.sh
Here the owner can read and write, everyone else can only read, and nobody can execute. Running ./deploy.sh produces Permission denied. The fix is to add the execute bit:
chmod +x deploy.sh
./deploy.sh
Avoid the shortcut of running sudo npm install -g or sudo before everything. sudo runs a command as the administrator, and files created that way become owned by root, which later causes EACCES errors for your normal user. Fix the permissions or the installation location instead.
7. Getting help
You do not need to memorize every flag.
ls --help # short built-in help (many Linux tools)
man grep # the manual page (q to quit)
npm help install
git help commit # you will use this in the next lesson
On macOS some commands do not support --help; use man. When you meet an unfamiliar error, read it from the top, copy the exact message into a search engine with the tool name, and check the official docs first.
8. Worked example: prepare the Harbor Workshops project
Task. You join the Harbor Workshops team on a new machine. Create the project folder, add the basic files, find every mention of "capacity" in a copied starter file, and prepare a repository-ready layout.
Step 1: Create the structure.
cd ~
mkdir -p projects
cd projects
mkdir -p harbor-workshops/src/components harbor-workshops/docs
cd harbor-workshops
pwd
# /Users/amira/projects/harbor-workshops
mkdir -p creates the intermediate folders in one command and does not fail if they already exist.
Step 2: Create files.
touch README.md src/App.jsx src/components/WorkshopCard.jsx
echo "# Harbor Workshops" > README.md
echo "node_modules" > .gitignore
echo ".env" >> .gitignore
echo "dist" >> .gitignore
cat .gitignore
# node_modules
# .env
# dist
Notice the first echo uses > because the file is new, and the others use >> to append. Using > three times would have kept only the last line.
Step 3: Add a starter file and search it.
cat > src/components/WorkshopCard.jsx <<'EOF'
export default function WorkshopCard({ title, capacity, booked }) {
const seatsLeft = capacity - booked;
// TODO: show a warning when capacity is nearly reached
return <p>{title}: {seatsLeft} seats left (capacity {capacity})</p>;
}
EOF
grep -rn -i "capacity" src
# src/components/WorkshopCard.jsx:1:export default function WorkshopCard({ title, capacity, booked }) {
# src/components/WorkshopCard.jsx:2: const seatsLeft = capacity - booked;
# src/components/WorkshopCard.jsx:3: // TODO: show a warning when capacity is nearly reached
# src/components/WorkshopCard.jsx:4: return <p>...
Step 4: Count and filter.
grep -rn "TODO" src | wc -l
# 1
Step 5: Check the layout and hidden files.
ls -la
# .gitignore README.md docs src
Why this approach and not others. Creating folders and files with commands is repeatable: you can paste these lines into a setup note for the next teammate. Using a graphical file manager works but cannot be copied into documentation. Using > for every line of .gitignore is wrong because each > overwrites the file. Searching with grep -r is better than opening every file in an editor because it shows all locations at once, with line numbers.
9. Comparison tables
Common commands by purpose
| Goal | Command | Notes |
|---|---|---|
| Where am I? | pwd |
Prints the absolute path |
| What is here? | ls, ls -la |
-a shows hidden files |
| Change folder | cd path |
cd .., cd ~, cd - |
| Make a folder | mkdir -p a/b |
-p for nested |
| Copy / move | cp, mv |
Overwrite silently without -i |
| Delete | rm, rm -r |
No trash; verify first |
| Read a file | cat, less, head, tail |
less for long files |
| Search content | grep -rn |
Exclude node_modules |
| Search names | find |
Supports wildcards |
Redirection operators
| Operator | Effect | Typical risk |
|---|---|---|
> |
Write output to a file | Overwrites existing content |
>> |
Append output to a file | Duplicates lines if rerun |
| |
Send output to another command | None, but order matters |
2> |
Redirect errors | Errors vanish if sent to a missing file you never read |
&& |
Run next only on success | Stops the chain at the first failure |
Absolute and relative paths
| Absolute | Relative | |
|---|---|---|
| Starts at | / or ~ |
The current directory |
| Works from any folder | Yes | No |
| Best for | Scripts, documentation, configuration that must always point to one place | Everyday navigation inside a project, portable project scripts |
10. Pitfalls and exam tips
- Pitfall: the wrong working directory. Many "it does not work" problems are simply running
npmorgitin the wrong folder. Runpwdandlsfirst.npmneedspackage.jsonin the current folder, andgitneeds to be inside a repository. - Pitfall: overwriting with
>. Use>>to append. A single wrong>can erase a configuration file. - Pitfall: deleting by wildcard.
rm *.jsremoves every matching file in the current folder. Preview the match withls *.jsbefore you delete. - Pitfall: spaces in paths. Quote them or avoid them.
- Pitfall:
sudoas a fix. It hides the real problem and creates root-owned files. - Pitfall: confusing the terminal and the shell. The terminal is the window; the shell interprets commands.
Exam tip. Pathway-style assessments describe a situation and ask which command achieves it. Identify the goal (navigate, create, move, search, combine) and then check the exact flag: -r for folders, -a for hidden files, -p for nested creation, >> to append. When two options look similar, ask "does this overwrite, delete, or ask first?"
Exam tip. If a question shows command not found, think of PATH and installation. If it shows Permission denied, think of permissions and chmod. If it shows No such file or directory, check the path, the case, and the current directory.
Mini case study: the missing test file
Situation. Noor, a new teammate, runs npm test in her home folder and sees npm ERR! enoent Could not read package.json. She then runs ls, sees her project folder, and decides to fix it by running sudo npm install in her home folder. Later she wants to know which source files still contain console.log before a release.
Questions.
- What is the real cause of the first error?
- Why is
sudo npm installthe wrong response? - Write the commands to find every
console.loginsrcand count the files.
Solution.
npmlooks forpackage.jsonin the current directory, and Noor is in her home folder, not the project. The fix iscd projects/harbor-workshops(verified withpwdandls), thennpm test.sudodoes not solve a wrong-directory problem, and it would install packages into the wrong place as root, creating root-owned files that cause permission errors later.- Use
grep -rn "console.log" srcfor the locations andgrep -rl "console.log" src | wc -lfor the number of files, because-llists each file once.
Key terms
- Terminal: the window that shows text input and output.
- Shell: the program that interprets your commands (bash, zsh, PowerShell).
- Path: the location of a file or folder; absolute or relative.
- Flag: an option that changes how a command behaves.
- Pipe (
|): connects one command's output to another's input. - Redirection: sending output to a file or reading input from one.
- Environment variable: a named value available to programs.
PATH: the ordered list of folders searched for commands.- Permission: the read, write, and execute rights of a file.
- Hidden file: a file whose name begins with a dot.
Summary checklist
- I can tell the terminal, the shell, and the file system apart.
- I can navigate with
pwd,ls,cd, and use.,.., and~. - I create files and folders with
mkdir -pandtouch. - I know that
rm,>,mv, andcpcan destroy data without warning. - I search with
grep -rnandfind, excludingnode_modules. - I can combine commands with pipes,
>,>>, and&&. - I can diagnose
command not foundwithPATHandPermission deniedwithchmod. - I keep secrets in
.envand out of version control. - I use tab completion, history, and
manto work faster.
