Skip to content

Terminal, Git, and Collaboration

Step 10 of 45

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

  1. Explain the roles of the terminal, the shell, and the file system, and read a path correctly.
  2. Navigate with pwd, ls, and cd, using absolute paths, relative paths, ., .., and ~.
  3. Create, copy, move, and delete files and folders with mkdir, touch, cp, mv, and rm, and know which operations cannot be undone.
  4. Read and search files with cat, less, head, tail, and grep.
  5. Combine commands with pipes and redirection.
  6. Describe environment variables, PATH, and file permissions at the level needed to diagnose common errors.
  7. Use tab completion, history, and --help or man to work faster and learn commands on your own.
  8. Prepare a project folder with a .gitignore, README.md, and package.json ready 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: clear or 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.

  1. rm has 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 as rm -rf ~ /tmp (note the space) can be catastrophic. Before deleting, run ls on 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.
  2. mv and cp overwrite silently. mv a.txt b.txt replaces b.txt if 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 npm or git in the wrong folder. Run pwd and ls first. npm needs package.json in the current folder, and git needs to be inside a repository.
  • Pitfall: overwriting with >. Use >> to append. A single wrong > can erase a configuration file.
  • Pitfall: deleting by wildcard. rm *.js removes every matching file in the current folder. Preview the match with ls *.js before you delete.
  • Pitfall: spaces in paths. Quote them or avoid them.
  • Pitfall: sudo as 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.

  1. What is the real cause of the first error?
  2. Why is sudo npm install the wrong response?
  3. Write the commands to find every console.log in src and count the files.

Solution.

  1. npm looks for package.json in the current directory, and Noor is in her home folder, not the project. The fix is cd projects/harbor-workshops (verified with pwd and ls), then npm test.
  2. sudo does 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.
  3. Use grep -rn "console.log" src for the locations and grep -rl "console.log" src | wc -l for the number of files, because -l lists 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 -p and touch.
  • I know that rm, >, mv, and cp can destroy data without warning.
  • I search with grep -rn and find, excluding node_modules.
  • I can combine commands with pipes, >, >>, and &&.
  • I can diagnose command not found with PATH and Permission denied with chmod.
  • I keep secrets in .env and out of version control.
  • I use tab completion, history, and man to work faster.

Official sources