Searching and Finding Things: grep and find

Learn to search inside files for text with grep and find files across the system with find.

~9 min Beginner

Two different questions

Searching on the command line means one of two things, and each has its own tool.

  • "Which lines contain the word timeout?" The tool is grep. It searches the text inside files.
  • "Where is the file called config.yml?" The tool is find. It searches for files and folders by name and other properties.

grep: search inside files

The basic form is grep pattern file. grep prints every line of the file that contains the pattern.

grep "error" server.log
grep -i "error" server.log
grep -n "error" server.log
grep -c "error" server.log
grep -v "debug" server.log
grep -r "TODO" ~/projects
grep -rl "password" /etc 2>/dev/null
  • The first command prints each line containing error.
  • -i ignores upper and lower case.
  • -n shows the line number in front of each match.
  • -c prints only how many lines matched.
  • -v inverts the match: it prints lines that do not contain the word.
  • -r searches recursively through every file in a folder.
  • -l prints only the names of files that contain a match.
  • 2>/dev/null hides error messages such as "Permission denied" (explained in the redirection lesson).

Another useful option is -w, which matches whole words only. Options can be combined, for example grep -rin "todo" ..

grep in a pipe

grep can read the output of another command instead of a file. Without a file name it reads from its input.

ps aux | grep nginx
history | grep git
dmesg | grep -i usb

This lets you filter the output of any command. ps aux lists running programs, history lists commands you ran earlier and dmesg prints system messages.

Patterns: a first look at regular expressions

The pattern does not have to be a fixed word. A regular expression is a pattern language for text. A few symbols are enough to start:

  • ^ matches the start of a line.
  • $ matches the end of a line.
  • . matches any single character.
  • * matches zero or more of the previous character.
  • [abc] matches one character from the list.
grep "^Error" log.txt
grep "done$" log.txt
grep "gr.y" words.txt
grep -E "cat|dog" pets.txt
grep -E "[0-9]{3}-[0-9]{4}" contacts.txt
  • ^Error matches lines that start with Error.
  • done$ matches lines that end with done.
  • gr.y matches gray and grey.
  • -E turns on extended expressions. cat|dog matches either word.
  • [0-9]{3}-[0-9]{4} matches three digits, a dash, then four digits.

You do not need to master these now. Knowing they exist is enough.

find: search for files

The form is find where tests. The first argument is the place to start looking. Everything after it narrows down the match.

find . -name "notes.txt"
find /home -name "*.jpg"
find . -iname "readme*"
find . -type d -name "node_modules"
  • . means the current folder and everything inside it.
  • -name matches the file name. Put patterns with * in quotes so find sees the wildcard instead of the shell.
  • -iname ignores case.
  • -type d keeps only directories. -type f keeps only regular files.

More tests: size, time and owner

find . -type f -size +100M
find . -mtime -7
find . -mtime +30
find . -user alex
  • -size +100M matches files larger than 100 megabytes. A minus sign means smaller.
  • -mtime -7 matches files modified less than 7 days ago. -mtime +30 means more than 30 days ago.
  • -user alex matches files owned by alex.

You can add several tests. They all have to match.

Doing something with the results

find . -name "*.tmp" -delete
find . -name "*.log" -exec wc -l {} \;
find . -name "*.txt" | xargs grep -l "invoice"
  • -delete removes every match.
  • -exec command {} \; runs a command once for each match. {} stands for the current file name.
  • xargs takes lines from a pipe and puts them on the end of another command, so this last line searches inside each .txt file that find found.
Always run find without -delete first. Check the list, then add -delete. A safe cleanup is: run find . -name "*.tmp", check that the list looks right, then run it again with -delete.

Quick alternatives

locate notes.txt
which python3
type ls
  • locate searches a prebuilt index, so it is instant. The index is updated with sudo updatedb, so very new files can be missing.
  • which python3 shows the path of a command.
  • type ls shows whether a name is a program, a built-in command or an alias.
Sign up to track your progress Mark lessons as read and pick up where you left off Sign up free to unlock this practice Your first practice lesson is free to try. Create an account to unlock the rest and save your progress