Course / 03 Command line / Lesson 10 of 19

find, grep, file, strings, and which

Estimated time: 20 min reading · 20 min activity

You remember a line in a note but not its location. A filename search asks where a name occurs; a content search asks which text is inside files. Decide which question you need to answer before choosing a tool.

find walks through a directory tree and tests its entries. grep searches input text and displays matching lines. A pattern is a rule describing a match. You will first use simple filename patterns and ordinary words, then connect each result to its source.

Before you begin

Estimated time
20 min reading, 20 min activity. Setup and optional practice may take longer.
Where you work
Use Bash in your owned Ubuntu practice environment as an ordinary user. The supplied text files use UTF-8, a text encoding; where shown, LC_ALL=C requests consistent text ordering. Work only under your own new ~/yanosec-lab directory, never a host share or personal/system file. Refuse an existing exercise destination rather than overwriting it. No account, paid platform, or remote target is required. Optional extensions take about 10–15 minutes and are not part of the time above. A virtual machine is optional. You can also finish the reasoning from the printed evidence.
Without a lab
The page supplies the files, source and text records needed for the activity. Without a shell, follow the numbered steps on paper, label each result as predicted, and use the separate evidence supplied by the question. Running commands can wait until your lab is available. Reading works without JavaScript. Answer checking needs JavaScript and a secure context, such as HTTPS; saving a correct result also needs usable browser storage. Missing tools, managed or mobile hosts, or a deferred guest setup never require buying a service. Keep owned lab files for review; do not use broad deletion.

After this lesson you can:

  • Choose find for names and grep for matching text.
  • Recover a fixed status line in a tiny owned tree.
  • Explain file, strings and command-location results without overclaiming.

01Example

The worked note notes.txt contains topic=demo on line 1 and status=WAIT on line 2. The first command selects .txt names beneath the current folder; the second searches the contents of one named file. The activity supplies a different tree.

Commands to read separately:
find . -type f -name '*.txt'
grep -n 'status' notes.txt

Complete worked notes.txt content:
topic=demo
status=WAIT

Predicted result of grep:
2:status=WAIT

-n adds the source line number.
The filename search does not itself inspect these content lines.

02Match the question to the evidence

In find . -type f -name '*.txt', the dot selects the current directory as the search root. -type f selects regular files. -name tests each entry's name against the pattern *.txt: the star can match a sequence of characters before the .txt ending.

Quotes matter because the shell also understands filename patterns. Keeping '*.txt' quoted passes that pattern to find unchanged. Without quotes, the shell may first replace it with matching names in the current directory, giving find a different set of arguments.

In grep -n 'status' notes/*.txt, the filename pattern is deliberately unquoted. The shell expands notes/*.txt into the matching .txt filenames in this tiny owned directory. The quoted word status is the text pattern passed to grep. A filename match is separate from a matching line inside that file.

grep -n adds a line number, counted from one within each file. With several files it also normally identifies the filename. Thus a result can tell you which file matched and where to inspect it. Matching is case-sensitive by default. No matching line and an error reading input are different outcomes.

file uses content and other tests to suggest a file type. strings extracts runs of printable characters, characters that can be displayed as text. Neither operation executes the file or proves its purpose, safety or complete format. One readable word inside bytes is only a clue.

type -a grep asks Bash which implementations the name can resolve to. The separate which command may be unavailable and does not describe every shell-specific case. Knowing a command's location helps identify its implementation; it does not establish that every use of it is safe.

Compare a filename predicate with a content predicate on the explicitly supplied notes.txt evidence.Model. A teaching model drawn by hand. It shows the idea, not real tool output.

Read the full explanation below.

find . -type f -name '*.txt'grep -n 'status' notes.txt

Filename predicate; this supplied notes.txt is a match, not a complete directory inventory.

Immutable supplied teaching corpus

Source filenameSource line numberImmutable source content
notes.txt1topic=demo
notes.txt2status=WAIT
Selected view

Result

notes.txt

Find tests the filename, not these content lines; the supplied filename is notes.txt.

Follow the explanation

  1. Find tests the filename, not these content lines; the supplied filename is notes.txt.
  2. grep matches source line 2, predicting 2:status=WAIT; 2: is not stored file content.
Read every state and value

1. Find tests the filename, not these content lines; the supplied filename is notes.txt.

View
name
Rows shown
notes.txt · 1 · topic=demo
Highlighted Cell Refs
Row: notes.txt · 1 · topic=demo; Column: Source filename
Result rows
Source Row: notes.txt · 1 · topic=demo; Cells: notes.txt

2. grep matches source line 2, predicting 2:status=WAIT; 2: is not stored file content.

View
grep
Rows shown
notes.txt · 2 · status=WAIT
Highlighted Cell Refs
Row: notes.txt · 2 · status=WAIT; Column: Source line number · Row: notes.txt · 2 · status=WAIT; Column: Immutable source content
Result rows
Source Row: notes.txt · 2 · status=WAIT; Cells: 2 · status=WAIT
Compare a filename predicate with a content predicate on the explicitly supplied notes.txt evidence.

03Use a fresh owned workspace

The paths lesson introduced ~/yanosec-lab: ~ expands to your home directory. Before a file activity, return with cd ~/yanosec-lab. Use pwd to check your location and ls -a to inspect names. Continue only if this is your recognized owned lab. Then create the lesson's new child directory.

If mkdir reports that a destination already exists, preserve that work. Choose an unused name and use it consistently, or follow the paper route. Enter one command at a time and continue only after the preceding step succeeds. Record an unexpected result before doing anything else.

Unless the lesson says otherwise, leave the small activity folder for review and return with cd ~/yanosec-lab when finished. Closing the terminal does not delete files you saved. These activities need no sudo or system-file changes.

04Try the supplied search tree

The inventory supplies every filename and every content line. It labels a worked note separately from the activity tree. Use the archive only if you want to repeat the file operations in your owned lab; the paper route follows exactly the same names and lines.

Before extraction, read the archive guide and compare the listed entries. During the activity, predict filename matches first, then text matches. This order makes it clear why readme.log can contain a status line yet be excluded by a .txt filename selection.

Find a name, then inspect matching content

The entries below contain every line in the tiny supplied tree.
*.txt is a filename pattern. Quoting it passes it unchanged to find;
leaving notes/*.txt unquoted lets the shell select these named files.
grep -n numbers lines from one in each source file.

Files contain exactly the shown lines.
search-tree/notes/alpha.txt:
  task=inventory
  status=WAIT
search-tree/notes/beta.txt:
  task=practice
  status=READY
search-tree/notes/readme.log:
  status=ARCHIVED
Owned activity: find . -type f -name '*.txt'
Then inspect cat notes/beta.txt and grep -n 'status' notes/beta.txt.
Predicted status line in beta.txt: 2:status=READY
Search all .txt files with grep -n 'status' notes/*.txt; order may vary.
Question task: search known text READY inside a file, not change its mode.

Download the complete search-tree contents and question task

Read an owned archive before extracting it

An archive bundles named entries. Extracting writes those entries back
to disk. A .tar.gz file uses tar bundling plus gzip compression; neither
operation encrypts the content. Use only the supplied owned archives.

All supplied archives contain original ordinary text files under one
named directory. No symlinks, executables with special modes, devices,
absolute paths or parent traversal entries are authored. Inspect first.
Save the chosen archive in the GUEST Downloads folder. If its actual
location differs, use that quoted absolute path; do not guess.
Use a new destination beneath ~/yanosec-lab, never an existing folder.
Example templates (replace ARCHIVE.tar.gz and NEW-DEST):
tar -tzf ~/Downloads/ARCHIVE.tar.gz
mkdir ~/yanosec-lab/NEW-DEST
tar -xzf ~/Downloads/ARCHIVE.tar.gz -C ~/yanosec-lab/NEW-DEST
Run the extraction only if mkdir succeeded and inventory matches.
t lists; x extracts; z handles gzip; f names archive; -C names target.
Keep original data; do not use sudo, overwrite flags or root extraction.
Stop on an unexpected path/link/member or download you cannot identify.
Fallback: read the full inline tree and contents; predict actions in notes.
Cleanup: leave scoped files for review; restore a guest baseline only
if all subsequent guest work is disposable. No broad rm command.

Download archive handling instructions

  1. At your lab root list tar -tzf ~/Downloads/search-tree.tar.gz after saving the owned archive there. Create mkdir search, then extract with tar -xzf ~/Downloads/search-tree.tar.gz -C ~/yanosec-lab/search only after creation succeeds and members match.
  2. Enter cd search/search-tree. Run find . -type f -name '*.txt'. Order is not graded. The .log file is excluded by name.
  3. Run grep -n 'status' notes/*.txt. It prints notes/alpha.txt:2:status=WAIT and notes/beta.txt:2:status=READY. Then use cat notes/beta.txt to connect the result to the complete file rather than an isolated guess.
  4. If installed, use file notes/beta.txt and strings notes/beta.txt; record actual output without assuming a fixed description. Run type -a grep to inspect resolution. Missing optional tools use the printed reasoning and await later package setup.
  5. On paper trace the same exact lines and patterns. Return to the lab root and retain this small tree; do not search your entire host, external systems or unknown files.

05Optional challenge

Allow about ten extra minutes. On paper, create a file named status.txt with no status line and another file containing status=READY. Explain why a name match cannot settle a content question. Then explain why a word found by strings cannot by itself establish a binary's purpose.

06Cards for the checks

The checks below use these cards. They are original fictional text, safe to read anywhere.

Independent file-content card: labels are filenames, indented rows are file linesOwned fixture. An original file made for this course. Follow the activity's instructions in your own lab.

field-tree/a.txt:
  owner=lab
  state=READY
field-tree/b.txt:
  state=WAIT
field-tree/c.log:
  state=READY

07Fresh cases for the checks

Use these fictional cases for the checks below. They have different inputs from the worked examples. Read them here or make notes; no installation or external service is needed.

Search card A: two independent command requestsOwned fixture. An original file made for this course. Follow the activity's instructions in your own lab.

Request F: from the owned search root, list regular files beneath . whose names end .log.
Use find with arguments in this order: root, -type f, -name, quoted pattern.
Request G: print lines containing the case-sensitive literal text phase from records/one.txt.
Include each matching line's source line number. Use grep with arguments in this
order: -n, pattern, filename. These are paper commands; no files need creating.

Search card B: fictional inspection recordsOwned fixture. An original file made for this course. Follow the activity's instructions in your own lab.

file parcel.bin reports: data
strings parcel.bin includes the printable sequence: backup
which grep reports: /opt/lab/bin/grep
No parcel.bin execution or implementation review is recorded.
Treat which only as the supplied command-location report, not a full shell-resolution test.

Search card C: optional changed filename selectionOwned fixture. An original file made for this course. Follow the activity's instructions in your own lab.

Complete inventory; indented rows are file contents, starting at line 1:
transfer/a.txt:
  mode=GO
transfer/b.txt:
  mode=WAIT
transfer/c.log:
  title=parcel
  mode=WAIT
Original paper command: grep -n WAIT transfer/*.txt
Changed command: replace only transfer/*.txt with transfer/*.log.
The glob expands to one file. With one filename grep -n prints number:content,
without a filename prefix. Every file is readable and no error occurs.

08Explain a search result

Optional self-check: explain the separate jobs of a filename pattern, a content pattern and a source line number. Then describe one limit of a file, strings or which result.

Check your explanation: identify who expands a glob, distinguish the selected filenames from the bytes searched by grep, count lines within each source file, and avoid turning a type, word or path into proof of behavior or safety.

09Common mistakes

If find results change depending on files in your current directory, inspect whether the name pattern was quoted and whether pwd is the intended owned root. Do not broaden to / to compensate.

If grep matches nothing, inspect the exact bytes, spelling/case and chosen files. grep is case-sensitive by default; a no-match result differs from an unreadable-input error.

If file/strings is absent, use the complete text evidence and record the tool gap. Do not install before the package lesson or infer maliciousness from a readable name.

References

  • Ubuntu 24.04 packaged manual: find(1)

    Use the named command and option sections. This manual describes Ubuntu 24.04 packages; your installed version can differ. The lesson supplies the facts needed for its activity.

  • Ubuntu 24.04 packaged manual: grep(1)

    Use the named command and option sections. This manual describes Ubuntu 24.04 packages; your installed version can differ. The lesson supplies the facts needed for its activity.

  • Ubuntu 24.04 packaged manual: file(1)

    Use the named command and option sections. This manual describes Ubuntu 24.04 packages; your installed version can differ. The lesson supplies the facts needed for its activity.

  • Ubuntu 24.04 packaged manual: strings(1)

    Use the named command and option sections. This manual describes Ubuntu 24.04 packages; your installed version can differ. The lesson supplies the facts needed for its activity.

  • Ubuntu 24.04 packaged manual: bash(1)

    Shell grammar, quoting, builtins, redirection and job control; use only the sections introduced in this lesson. Use the named command and option sections. This manual describes Ubuntu 24.04 packages; your installed version can differ. The lesson supplies the facts needed for its activity.