03 of 10 — Terminal Mastery
A practical guide to finding files, searching text, reading content, and filtering results on Windows, macOS, and Linux.

Imagine you're working on a large React application.

Your project contains hundreds of components, thousands of lines of code, configuration files, and documentation.

You remember using a function called getUserData, but you can't remember which file contains it.

What do you do?

Open every file individually?

Search through folders manually?

There is a much better solution.

You use your terminal.

The command line provides powerful tools for finding files, searching their contents, reading logs, and filtering large amounts of information.

In this article, we'll explore these tools across Windows PowerShell, macOS, and Linux.

By the end, you'll know how to:

  • Find files by name and extension.
  • Search for specific text inside files.
  • Read files directly from the terminal.
  • Inspect large log files efficiently.
  • Display only the lines you need.
  • Combine search operations.
  • Search through real development projects.

Let's get started.

1. Finding Files and Directories

The first skill we'll learn is finding files by their names.

Imagine you have this project:

my-project/ ├── src/ │ ├── components/ │ │ ├── Header.jsx │ │ └── Footer.jsx │ ├── utils/ │ │ └── helpers.js │ └── App.jsx ├── public/ │ └── logo.svg ├── package.json └── README.md 

You want to locate helpers.js, but you don't remember its exact directory.

Let's solve that.

Linux and macOS: The find Command

The find command searches for files and directories within a specified location.

Basic syntax:

find [path] [expression] 

To search for a file named helpers.js:

find . -name "helpers.js" 

Let's understand this command:

  • find starts the search.
  • . means the current directory.
  • -name specifies the filename pattern.
  • "helpers.js" is the name we're searching for.

Possible output:

./src/utils/helpers.js 

Find All JavaScript Files

find . -name "*.js" 

This searches recursively for files ending in .js.

To find both .js and .jsx files:

find . -type f \( -name "*.js" -o -name "*.jsx" \) 

Here:

  • -type f restricts results to regular files.
  • -o means OR.
  • \( and \) group expressions.

Find Only Directories

find . -type d 

Find Files with a Specific Extension

find . -type f -name "*.json" 

This is especially useful when working with configuration-heavy projects.

2. Finding Files in Windows PowerShell

PowerShell provides its own filesystem search capabilities.

The most useful starting point is Get-ChildItem.

Search for a Specific Filename

Get-ChildItem -Path . -Filter "helpers.js" -Recurse 

Let's break it down:

  • Get-ChildItem retrieves filesystem items.
  • -Path . starts in the current directory.
  • -Filter specifies the filename.
  • -Recurse searches through subdirectories.

Find All JavaScript Files

Get-ChildItem -Path . -Filter "*.js" -Recurse -File 

The -File option ensures that only files are returned.

Find All React Components

Get-ChildItem -Path . -Include "*.jsx", "*.tsx" -Recurse -File 

This is useful when exploring React or TypeScript projects.

Find Directories Only

Get-ChildItem -Path . -Directory -Recurse 

Search by Filename Using Wildcards

Get-ChildItem -Path . -Recurse -File | Where-Object { $_.Name -like "*config*" } 

This finds files whose names contain config.

For example:

vite.config.js tsconfig.json config.ts 

PowerShell's Where-Object allows you to filter objects based on conditions.

We'll explore pipelines more deeply in Article 04.

3. Finding Files in Windows Command Prompt

Command Prompt also supports recursive file searches.

Use:

where /r . helpers.js 

This searches recursively from the current directory.

To find all JavaScript files:

where /r . *.js 

The where command can search for matching files in directory trees.

Don't confuse it with PowerShell's Where-Object.

They are different commands with different purposes.

4. Reading Files from the Terminal

Finding a file is only half the job.

Now you need to inspect its contents.

Let's explore the most common ways to read files.

Linux and macOS: The cat Command

cat displays file contents directly in the terminal.

cat README.md 

Example output:

# My Project This is a React application. ## Installation npm install 

You can also display multiple files:

cat file1.txt file2.txt 

This prints their contents one after another.

Important: cat is useful for short files, but it can become inconvenient when reading very large files.

That's where other commands come in.

Windows PowerShell: Get-Content

PowerShell provides:

Get-Content README.md 

You can also use its alias:

gc README.md 

For reading a file line by line:

Get-Content README.md 

PowerShell returns the file's contents as objects representing lines of text.

Windows CMD: type

Command Prompt uses:

type README.md 

This displays the contents of the specified file.

5. Reading Large Files Efficiently

Imagine you're inspecting a server log containing 50,000 lines.

Displaying the entire file isn't always practical.

Instead, you can inspect only the beginning or end.

The head Command

On Linux and macOS:

head logfile.txt 

By default, this displays the first 10 lines.

To display the first 20 lines:

head -n 20 logfile.txt 

The tail Command

To display the last 10 lines:

tail logfile.txt 

To display the last 20 lines:

tail -n 20 logfile.txt 

Follow a Log File in Real Time

One of the most useful terminal tricks is:

tail -f application.log 

This continuously displays new lines as they are added to the file.

It's especially useful when monitoring application logs or debugging a running server.

Press Ctrl + C to stop following the file.

PowerShell Alternatives

Display the first 10 lines:

Get-Content application.log -TotalCount 10 

Display the last 10 lines:

Get-Content application.log -Tail 10 

Follow a log file as it changes:

Get-Content application.log -Wait 

This is the PowerShell equivalent of a common tail -f workflow.

What About CMD?

CMD doesn't provide direct equivalents of head and tail as built-in commands.

You can use:

more application.log 

This lets you view content page by page.

For more advanced inspection, PowerShell is usually the better option on Windows.

6. Searching for Text Inside Files

Now we reach one of the most powerful terminal skills.

Suppose you want to find every occurrence of:

getUserData 

inside your source code.

Instead of opening every file, you can search recursively.

Linux and macOS: The grep Command

grep searches text using patterns.

Basic syntax:

grep "search-term" filename 

Example:

grep "getUserData" app.js 

This displays matching lines from app.js.

Search Recursively

grep -R "getUserData" ./src 

The -R option searches through directories recursively.

Display Line Numbers

grep -Rn "getUserData" ./src 

The -n option includes line numbers.

Example output:

./src/services/user.js:15:const getUserData = () => {}; ./src/components/Profile.jsx:8:import { getUserData } from "../services/user"; 

Now you know exactly where the function appears.

Case-Insensitive Search

grep -Ri "getuserdata" ./src 

The -i option ignores letter case.

Search Only Specific File Types

grep -Rn --include="*.js" "getUserData" ./src 

This restricts the search to JavaScript files.

You can also search multiple extensions:

grep -Rn --include="*.js" --include="*.jsx" "getUserData" ./src 

7. Searching Text in Windows PowerShell

PowerShell provides a powerful command called Select-String.

It's similar to grep, but it works with PowerShell's object-based pipeline.

Search Inside a File

Select-String -Path "app.js" -Pattern "getUserData" 

Search Recursively

Get-ChildItem -Path .\src -Recurse -File | Select-String -Pattern "getUserData" 

This searches every file under src.

Include Line Numbers

PowerShell's Select-String includes line information in its results.

Example:

src\services\user.js:15:const getUserData = () => {}; 

Case-Insensitive Search

By default, Select-String searches case-insensitively.

You can explicitly use:

Select-String -Path "app.js" -Pattern "getuserdata" -CaseSensitive 

Search Only JavaScript Files

Get-ChildItem -Path .\src -Filter "*.js" -Recurse -File | Select-String -Pattern "getUserData" 

You can also search JSX files:

Get-ChildItem -Path .\src -Include "*.js", "*.jsx" -Recurse -File | Select-String -Pattern "getUserData" 

8. Searching Text in Windows CMD

Command Prompt provides the findstr command.

It can search for text inside files.

Search Inside a File

findstr "getUserData" app.js 

Search Recursively

findstr /S "getUserData" src\*.js 

The /S option searches through subdirectories.

Include Line Numbers

findstr /N "getUserData" app.js 

Case-Insensitive Search

findstr /I "getuserdata" app.js 

Search Multiple Files

findstr "React" *.js 

findstr is useful for simple text searches, although its pattern-matching behavior differs from grep and PowerShell's Select-String.

9. Reading Specific Lines from a File

Sometimes you don't need an entire file.

You only need a particular section.

For example, imagine a configuration file contains 500 lines, and you want to inspect lines 20 through 30.

Linux and macOS

Combine sed with a line range:

sed -n '20,30p' config.txt 

Here's what the options mean:

  • -n disables automatic printing.
  • 20,30 specifies the line range.
  • p prints the selected lines.

You can also use:

sed -n '20p' config.txt 

This displays only line 20.

PowerShell

Use Get-Content with Select-Object:

Get-Content config.txt | Select-Object -Skip 19 -First 11 

Why skip 19?

Because PowerShell's -Skip counts from zero, while humans usually count lines starting from one.

This displays lines 20 through 30.

CMD

You can combine more with line-number skipping:

more +19 config.txt 

This starts displaying the file from approximately the twentieth line.

For precise line-range selection, PowerShell or another dedicated text-processing tool is preferable.

10. Counting Lines, Words, and Characters

Sometimes you want to understand the size of a file without opening it.

Linux and macOS provide the wc command.

Count Lines

wc -l app.js 

Count Words

wc -w README.md 

Count Bytes

wc -c app.js 

Count Characters

wc -m app.js 

These commands are especially useful when analyzing logs, documentation, or large source files.

PowerShell

Count lines:

(Get-Content app.js).Count 

Count characters:

(Get-Content app.js -Raw).Length 

The -Raw parameter reads the file as one string instead of returning individual lines.

CMD

You can count lines using:

find /C /V "" app.js 

This is a common CMD technique for counting non-empty strings, though blank-line handling can make it less suitable as an exact general-purpose line counter.

For reliable text analysis on Windows, PowerShell offers more flexibility.

11. Combining Search Operations

Now let's combine what we've learned.

Imagine you have a React project and want to find every occurrence of useState inside JavaScript and JSX files.

Linux / macOS

grep -Rn \ --include="*.js" \ --include="*.jsx" \ "useState" ./src 

This searches recursively and displays line numbers.

PowerShell

Get-ChildItem .\src -Recurse -File | Where-Object { $_.Extension -in ".js", ".jsx" } | Select-String -Pattern "useState" 

This performs the same general task using PowerShell objects and pipelines.

CMD

findstr /S /N "useState" src\*.js src\*.jsx 

Now imagine searching for a function across an entire project containing hundreds of files.

A few commands can save you a lot of manual work.

Developer tip: In real projects, you may eventually want a faster search tool called ripgrep (rg). We'll introduce modern developer tools in Article 08.

12. A Real-World Debugging Exercise

Let's apply these skills to a realistic situation.

Imagine your Node.js application writes errors to a file called server.log.

You want to find every line containing the word ERROR.

Linux / macOS

grep -in "ERROR" server.log 

This searches without considering letter case and displays line numbers.

PowerShell

Select-String -Path server.log -Pattern "ERROR" 

CMD

findstr /I /N "ERROR" server.log 

Now suppose you only want the latest 20 lines of the log.

Linux / macOS:

tail -n 20 server.log 

PowerShell:

Get-Content server.log -Tail 20 

And if you want to monitor new log entries:

Linux / macOS:

tail -f server.log 

PowerShell:

Get-Content server.log -Wait 

This is a common debugging workflow when working with backend applications.

13. Common Mistakes to Avoid

Here are some mistakes beginners frequently make.

1. Searching the wrong directory

Always verify your current location before starting a search.

pwd 

Or in PowerShell:

Get-Location 

2. Forgetting recursive search

A search inside the current directory doesn't necessarily include all nested directories unless you request recursion.

3. Confusing find and grep

On Unix-like systems:

  • find locates filesystem entries.
  • grep searches text inside files.

They solve different problems.

4. Printing enormous files

Avoid displaying thousands of lines when you only need a small section.

Use head, tail, less, or PowerShell's Select-Object.

5. Searching generated directories unnecessarily

JavaScript projects often contain directories such as:

node_modules/ dist/ build/ 

Searching these directories can produce enormous amounts of irrelevant output.

Exclude them when appropriate.

For example:

grep -Rn \ --exclude-dir=node_modules \ --exclude-dir=dist \ "useState" . 

6. Assuming every search tool uses the same syntax

grep, findstr, and Select-String have different options and pattern-matching rules.

Learn the tool you're actually using.

14. Practice Challenges

Time to put your knowledge to work.

Create a directory named search-lab and add these files:

search-lab/ ├── app.js ├── helpers.js ├── README.md ├── config.json └── logs/ └── server.log 

Put the following content in app.js:

function getUserData() { return { name: "Alex" }; } function getProducts() { return []; } console.log(getUserData()); 

Put this in helpers.js:

function formatName(name) { return name.trim(); } function calculateTotal(items) { return items.length; } 

Put this in server.log:

INFO Server started INFO Database connected ERROR Database connection timeout INFO Retrying connection ERROR Authentication failed INFO Server stopped 

Now complete these challenges.

Challenge 1: Find Files

Find all .js files inside search-lab.

Challenge 2: Search for a Function

Find every occurrence of getUserData and display the line numbers.

Challenge 3: Search for Errors

Find every line containing ERROR inside server.log.

Challenge 4: Inspect a File

Display the first two lines of server.log.

Challenge 5: Count Lines

Count the number of lines in helpers.js.

Challenge 6: Find Configuration Files

Find every .json file inside your project.

Challenge 7: Combine Your Skills

Search the entire project for the word function, but exclude any generated or dependency directories if they exist.

Try solving every challenge using your operating system's native shell.

Quick Command Reference

Task Linux / macOS PowerShell CMD
Find files find Get-ChildItem where /r
Read file cat Get-Content type
First lines head Select-Object -First more
Last lines tail Get-Content -Tail more
Follow logs tail -f Get-Content -Wait —
Search text grep Select-String findstr
Count lines wc -l .Count find /C /V ""
Show line ranges sed Select-Object more +N

Remember that these are functional equivalents for common tasks, not identical implementations.

What's Next?

You can now locate files, search through source code, inspect logs, and extract useful information without manually opening every file.

But something even more powerful is waiting.

So far, we've mostly executed individual commands.

What happens when you want to combine several commands into one workflow?

For example:

  • Find all JavaScript files.
  • Search them for a specific function.
  • Filter the results.
  • Save the output into a separate file.

This is where Pipes, Redirection, and Command Chaining come in.

In Article 04, we'll explore how commands communicate with each other and how to build powerful workflows from simple operations.

Next Article: Pipes, Redirection and Command Chaining

Final Thoughts

Searching through files is one of those skills that seems simple until you start working on large projects.

Once you become comfortable with find, grep, Select-String, and the other tools covered here, you'll spend much less time searching manually.

The terminal isn't just a place to execute commands.

It's a powerful environment for exploring, inspecting, and understanding your entire codebase.

Learn to search efficiently, and you'll spend more time building and less time looking for things.

Happy coding!