23  23. Searching, Counting, and Sorting

This page shows the commands that find things on the command line: grep finds text inside files, and find finds files by name. Then come wc, sort, head and tail, which count, sort and trim what you found. These commands work well in pipes (see Wildcards and Pipes). The examples use the practice files from Files, Folders, and Paths.

23.1 Searching inside files: grep

grep prints the lines of a file that contain a word or phrase. First, give the notes some content (this replaces what you wrote on earlier pages):

cd ~/Documents/bash-tutorial-files/documents/notes
echo "Budget review on Monday" > meeting-notes.txt
echo "Action: Maria updates the budget" >> meeting-notes.txt
echo "Action: Sam books the room" >> meeting-notes.txt
echo "Idea: a budget tracker app" > ideas.txt
grep budget meeting-notes.txt

Output:

Action: Maria updates the budget

grep is case-sensitive, so it skipped Budget. These options change that and more:

Option Meaning Example
-i ignore upper/lower case grep -i budget meeting-notes.txt
-n show line numbers grep -n Action meeting-notes.txt
-r search all files in a folder and its subfolders grep -r budget .
grep -i budget meeting-notes.txt
grep -n Action meeting-notes.txt

Output:

Budget review on Monday
Action: Maria updates the budget
2:Action: Maria updates the budget
3:Action: Sam books the room

When grep searches several files, it puts the file name in front of each match. Options can be combined. From the documents folder:

cd ..
grep -r -i -n budget .

Output (the files may be listed in a different order):

./notes/meeting-notes.txt:1:Budget review on Monday
./notes/meeting-notes.txt:2:Action: Maria updates the budget
./notes/ideas.txt:1:Idea: a budget tracker app

Always tell grep -r which folder to search (. means the current folder). If grep finds nothing, it prints nothing.

23.2 Finding files by name: find

find searches a folder and all of its subfolders for names that match a pattern. From bash-tutorial-files:

cd ~/Documents/bash-tutorial-files
find . -name "*.css"

Output:

./projects/website/styles.css

The . means “start searching here”. Put the pattern in quotes so the shell passes it to find unchanged instead of expanding it first. find matches folder names too; add -type f to list only files:

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

Output:

./documents/reports
./documents/reports/quarterly-report.txt
./documents/reports/quarterly-report.txt

The first command found the folder reports and the file inside it; the second found only the file. (Use -iname instead of -name to ignore upper/lower case.)

23.3 Counting and sorting: wc, sort, head, tail

Create a small data file:

cd ~/Documents/bash-tutorial-files/projects/data-analysis
echo "East,500" > data.csv
echo "West,750" >> data.csv
echo "North,320" >> data.csv
echo "South,610" >> data.csv
echo "East,410" >> data.csv
Command What it does
wc -l data.csv counts the lines (wc = “word count”; without -l it also counts words and characters)
sort data.csv prints the lines in alphabetical order (-r reverses, -n sorts numbers by value)
head -n 3, tail -n 3 the first / last lines (see Writing to Files)
wc -l data.csv
sort data.csv

Output:

5 data.csv
East,410
East,500
North,320
South,610
West,750

(On a Mac, wc puts some spaces in front of the number.)

These small commands become powerful in pipelines. How many rows are for the East region? Which two rows come first alphabetically?

grep East data.csv | wc -l
sort data.csv | head -n 2

Output:

2
East,410
East,500

23.4 Saving results to a file

Pipes and searches combine with redirection (>) from Writing to Files, so you can keep the results:

cd ~/Documents/bash-tutorial-files/documents/notes
grep -n Action meeting-notes.txt > action-items.txt
cat action-items.txt

Output:

2:Action: Maria updates the budget
3:Action: Sam books the room

Other examples: find . -name "*.jpg" > photo-list.txt saves a list of photos, and history | grep git > git-commands.txt saves your past Git commands.

23.5 How Claude Code searches your files

As of Oct 6, 2026 · Official docs: Tools reference

When Claude Code needs to find something in your project, it uses exactly these ideas. On a Mac (and on Linux), it searches by running find and grep commands through its Bash tool (using its own built-in versions of these programs), so commands like the ones on this page are literally what you’ll see it run. On Windows, it has two built-in tools for this instead: Glob, which finds files whose names match a wildcard pattern such as **/*.js (all .js files in any subfolder), and Grep, which searches inside files. You’ll meet Claude Code’s tools in How Claude Code Works.

Practice Questions

Easy

Question 1 · Matching

Match each command or option with its meaning.

Command or option Meaning
1. grep -i A. search all files in a folder and its subfolders
2. grep -n B. find files whose names match a pattern
3. grep -r C. ignore upper/lower case
4. find . -name D. show line numbers

1 → C, 2 → D, 3 → A, 4 → B.

Question 2 · Short answer

What does wc -l report.txt tell you?

The number of lines in report.txt (followed by the file name).

Question 3 · True or false

grep budget notes.txt also prints the lines that contain Budget (with a capital B).

False. grep is case-sensitive, so budget doesn’t match Budget. Add -i to ignore upper/lower case: grep -i budget notes.txt.

Medium

Question 4 · Write the command

Search all files in the current folder and its subfolders for the word invoice, ignoring upper/lower case and showing line numbers.

grep -r -i -n invoice .

(grep -rin invoice . is the same thing, with the options combined.)

Question 5 · Write the command

Give two different commands that count the lines in sales.csv.

wc -l sales.csv
cat sales.csv | wc -l

The first gives the file name to wc directly; the second pipes the file’s contents into wc. (The second prints only the number.)

Question 6 · Write the command

Write a command that finds all .jpg files in the current folder and all of its subfolders.

find . -name "*.jpg"

The quotes make sure find, not the shell, handles the *.

Question 7 · Write the command

Save every line of meeting-notes.txt that contains Action into a new file action-items.txt, then display the new file.

grep Action meeting-notes.txt > action-items.txt
cat action-items.txt

Hard

Question 8 · Scenario

In bash-tutorial-files, Maria forgets the quotes and types find . -name *.txt. It prints only ./README.txt, even though the documents subfolders contain several more .txt files. Explain why.

Without quotes, the shell expands *.txt before find runs, using the files in the current folder. The only match there is README.txt, so the command that actually runs is find . -name README.txt, which finds only files named exactly README.txt. With quotes, find . -name "*.txt", the pattern reaches find unchanged, and find applies it in every subfolder. (In a folder with several .txt files, the unquoted version fails with an error instead.)

Question 9 · Long answer

Using the data.csv file from this page, explain what each part of this pipeline does and what it prints:

sort -t, -k2 -n data.csv | tail -n 1
  • sort -t, -k2 -n data.csv sorts the lines using the comma as the separator between columns (-t,), by the second column (-k2), as numbers (-n), smallest first.
  • | sends that sorted list to the next command.
  • tail -n 1 keeps only the last line, which is the row with the largest number.

It prints West,750: the region with the highest sales.

Question 10 · Short answer

Why does find . -name "*report*" list ./documents/reports in addition to quarterly-report.txt? How do you list only files?

find checks the names of folders as well as files, and the folder name reports contains report. Add -type f to keep only regular files: find . -name "*report*" -type f.

Question 11 · Write the command

Write one pipeline that counts how many times you have run git commit according to your shell history.

history | grep "git commit" | wc -l

history lists your past commands, grep keeps the lines containing git commit, and wc -l counts them. (In zsh on a Mac, use history 1 instead of history to include the whole history. The count may also include the pipeline itself, since it contains git commit too.)

Question 12 · Scenario

While working on Maria’s Mac, Claude Code runs this command:

grep -rn "checkout" src

What is it doing, and why is it useful for you to be able to read it?

It searches every file in the src folder and its subfolders (-r) for the text checkout, and prints each matching line with its file name and line number (-n). It’s a read-only search, so it doesn’t change anything. On a Mac, Claude Code searches your project by running ordinary find and grep commands like this one; being able to read them lets you follow what it’s doing and spot a command that does something you didn’t expect.

© 2025-2026 Y. Rosenthal. All rights reserved.