Working Code
Example 1: Searching text with grep
Start with a file to search:
cat Documents/notes.md
Output:
# Notes
- item 1
- item 2
Find lines containing a specific word:
grep "item" Documents/notes.md
Output:
- item 1
- item 2
Show line numbers too:
grep -n "item" Documents/notes.md
Output:
2:- item 1
3:- item 2
Example 2: Case-insensitive search
grep -i "hello" Documents/hello.txt
Output:
Hello, World!
The -i option ignores case. It matches Hello, hello, and HELLO alike.
Example 3: Chaining commands with pipes
# Filter ls output for a specific pattern
ls | grep ".md"
Output:
notes.md
# Count items in a file listing
ls | wc -l
Output:
4
# 3-stage pipe: ls -> grep -> wc
ls | grep ".txt" | wc -l
Output:
1
Try It Yourself
grep with Various Options
# Search across multiple files
grep "Hello" Documents/hello.txt Documents/notes.md
# Recursive search through subdirectories
grep -r "item" Documents/
# Show only filenames (not content)
grep -rl "Hello" .
# Show match count only
grep -c "item" Documents/notes.md
Output:
2
# Show non-matching lines (inverse search)
grep -v "item" Documents/notes.md
Output:
# Notes
Finding Files with find
# Find files by name
find . -name "*.txt"
Example output:
./Documents/hello.txt
./Downloads/readme.txt
# Filter by type (f=file, d=directory)
find . -type f -name "*.md"
# Files modified within the last day
find . -mtime -1
# Files larger than a specific size
find . -size +1k
# Run a command on each found file (-exec)
find . -name "*.txt" -exec cat {} \;
"Why?" — Why Pipes Are Powerful
The pipe (|) connects one command's stdout to the next command's stdin.
ls -la | grep ".txt" | wc -l
| | |
file list .txt filter count lines
Step by step:
ls -la— list filesgrep ".txt"— keep only lines containing.txtwc -l— count remaining lines
Result: the number of .txt files in the current directory.
The core principle of pipes: combine simple tools to tackle complex tasks. Each command does one thing well, and pipes connect them to solve bigger problems.
grep Options Summary
| Option | Description | Example |
| ------ | ---------------------- | ----------------- |
| -i | Ignore case | grep -i "hello" |
| -n | Show line numbers | grep -n "error" |
| -r | Include subdirectories | grep -r "bug" . |
| -l | Show filenames only | grep -rl "todo" |
| -v | Exclude matches | grep -v "#" |
| -c | Count matching lines | grep -c "error" |
grep and Pipes in Practice
# Find errors in a log
cat app.log | grep "ERROR"
# Count error lines
cat app.log | grep "ERROR" | wc -l
# View everything except debug lines
cat app.log | grep -v "DEBUG"
# Find a function in source code
grep -rn "getUserById" src/
Common Mistakes
Mistake 1: Special characters in grep patterns
# . means "any character" in regex
grep "file.txt" . # matches file.txt AND file_txt
# To search literally, escape it
grep "file\.txt" .
# Or use -F (fixed string)
grep -F "file.txt" .
Mistake 2: Searching a directory without -r
grep "text" Documents/ # error
# grep: Documents/: Is a directory
grep -r "text" Documents/ # correct
Mistake 3: Piping find results to grep incorrectly
# Wrong: this searches filenames, not file contents
find . -name "*.txt" | grep "hello" # finds files with "hello" in the name
# Correct: search file contents
grep -r "hello" --include="*.txt" .
Deep Dive
Pattern searching with regex
grep supports regular expressions:
# ^ : start of line
grep "^-" Documents/notes.md
# $ : end of line
grep "2$" Documents/notes.md
# . : any single character
grep "ite.1" Documents/notes.md
# []: one character from a set
grep "[12]" Documents/notes.md
# Extended regex (-E)
grep -E "item [12]" Documents/notes.md
Regex is powerful but can be tricky at first. Basic grep options handle most searches, so learn regex as needed.
The powerful -exec option in find
Run a command on each found file:
# Delete all .log files
find . -name "*.log" -exec rm {} \;
# Print contents of all .txt files
find . -name "*.txt" -exec cat {} \;
# Save found file list to a file (using redirection)
find . -name "*.md" > md-files.txt
{} is replaced with the found file path, and \; marks the end of the command.
Why developers use ripgrep (rg) instead of grep
Many developers prefer rg (ripgrep):
brew install ripgrep
# Basic usage (similar to grep -r)
rg "functionName" src/
# Automatically respects .gitignore
# Color output by default
# Tens of times faster than grep
Especially effective on large codebases with tens of thousands of files. VS Code's search feature uses ripgrep internally.
- Search for text with
grep "Hello" Documents/hello.txt. - Search with line numbers using
grep -n "item" Documents/notes.md. - Count matching lines with
grep -c "item" Documents/notes.md. - List only .txt files with
ls | grep ".txt". - Search the entire current directory with
grep -r "Hello" ..
Q1. What does ls | grep ".txt" | wc -l output?
- A) The contents of .txt files
- B) The number of items containing ".txt" in their name in the current directory
- C) The total size of .txt files
- D) A list of .txt files