Time to study: ~60 min
You will learn: how to search for text inside files with grep, and how to search for files themselves with find.
← Chapter 3 | back to Terminal 101 | next: Chapter 5 →
before we start, all the examples below are run from inside the
Terminal-101dir, so the file tree is this one:
Terminal-101/
├── README.md
├── CHEATSHEET.md
├── 01-command-line-basics/
│ └── README.md
├── 02-the-linux-file-system/
│ └── README.md
├── 03-files-and-navigation/
│ └── README.md
├── 04-search-grep-find/
│ ├── README.md
│ └── fruits.txt
└── ... (chapters 5 to 9, each with a README.md)
1. the grep command (finding text)
grepis when u as a normal user want to search for something and u use the keymapctrl+for the search bar at the top of ur window.grepbasically has the same behaviour here. u can think about it like thectrl+fof the terminal.
- example: i want to search for the word
Helloin the file01-command-line-basics/README.md:
grep "Hello" 01-command-line-basics/README.mdecho "Hello World"
> this is basically the same as writing "Hello World" in a text editor, it prints `Hello World` to the terminal.
Hello World
echo "Hello everyone! My name is $name $surname. I am $age years old, and I work as a $job."
so
grepprints back every line that contains the word, not the word alone. this is the thing most people get wrong the first time.
we can also use it to grep from more than one file:
grep "Hello" 01-command-line-basics/README.md 02-the-linux-file-system/README.md01-command-line-basics/README.md:echo "Hello World"
01-command-line-basics/README.md:Hello World
01-command-line-basics/README.md:echo "Hello everyone! My name is $name $surname..."
notice what changed: when u pass more than one file,
grepputs the file name in front of every line so u know where each result came from. with one file it doesn’t, because there is nothing to be confused about.
we can also use the
-rflag to grep from all the files in the current dir. the.here means the current dir, so it searches every file under it recursively.
grep -r "Hello" ../01-command-line-basics/README.md:echo "Hello World"
./01-command-line-basics/README.md:Hello World
./01-command-line-basics/README.md:echo "Hello everyone! My name is $name $surname..."
./03-files-and-navigation/README.md:echo "Hello World" > hello.txt
for the next flags we will use a small file so u can actually see what changes. this is
fruits.txt:
cat fruits.txtapple
Banana
cherry
apple pie
the
-iflag makes the search case insensitive:
grep "banana" fruits.txt(nothing, because the file has "Banana" with a capital B)
grep -i "banana" fruits.txtBanana
the
-vflag inverts the search, it shows all the lines that do not contain the thing u are searching for:
grep -v "apple" fruits.txtBanana
cherry
the two
applelines are gone and everything else stayed. this is very useful later when u want to filter out noise from a log file.
the
-nflag shows u the line number of every match:
grep -n "apple" fruits.txt1:apple
4:apple pie
- these flags can be combined like any other flags:
grep -in "BANANA" fruits.txtsearches case insensitively and shows the line number.
2. the find command (finding files)
previously we searched for a word inside files, but now we are trying to find the files themselves.
- example: i want to find the file
README.mdinside the02-the-linux-file-systemdir:
find 02-the-linux-file-system/ -name "README.md"02-the-linux-file-system/README.md
the first argument is where to search and the
-nameis what to search for. so we can pass.to search the current dir instead if we want:
find . -name "README.md"./README.md
./01-command-line-basics/README.md
./02-the-linux-file-system/README.md
./03-files-and-navigation/README.md
./04-search-grep-find/README.md
./05-permissions-sudo/README.md
./06-text-editors/README.md
./07-scripts-env-path/README.md
./08-io-pipes-processes/README.md
./09-bash-scripting/README.md
now a bit more advanced searching. we can use
*to match anything, so we can search for all the files that end with.md:
find . -name "*.md"./README.md
./01-command-line-basics/README.md
./02-the-linux-file-system/README.md
./03-files-and-navigation/README.md
./04-search-grep-find/README.md
./05-permissions-sudo/README.md
./06-text-editors/README.md
./07-scripts-env-path/README.md
./08-io-pipes-processes/README.md
./09-bash-scripting/README.md
or we can use
*word*to match anything that contains that word:
find . -name "*fruit*"./04-search-grep-find/fruits.txt
or
word*to match anything that starts with that word:
find . -name "READ*"./README.md
./01-command-line-basics/README.md
./02-the-linux-file-system/README.md
./03-files-and-navigation/README.md
./04-search-grep-find/README.md
./05-permissions-sudo/README.md
./06-text-editors/README.md
./07-scripts-env-path/README.md
./08-io-pipes-processes/README.md
./09-bash-scripting/README.md
there is also
?which matches exactly one character, not any number of them like*does.
find . -name "0?-*"./01-command-line-basics
./02-the-linux-file-system
./03-files-and-navigation
./04-search-grep-find
./05-permissions-sudo
./06-text-editors
./07-scripts-env-path
./08-io-pipes-processes
./09-bash-scripting
so
0?matched01up to09, one character after the zero. if u wrote0??-*it would match nothing here, because there is no folder with 3 characters before the dash.
one more flag u will use a lot,
-type, which filters files or directories only:
find . -type d.
./01-command-line-basics
./02-the-linux-file-system
./03-files-and-navigation
./04-search-grep-find
./05-permissions-sudo
./06-text-editors
./07-scripts-env-path
./08-io-pipes-processes
./09-bash-scripting
find . -type f -name "*.txt"./04-search-grep-find/fruits.txt
-
dmeans directory andfmeans file. -
these are the most used flags and cases u need. for anything else,
man grepandman findare there.
NOTES
-
grepsearches inside files,findsearches for files. this is the whole difference and it is easy to mix them up at the beginning. -
always put ur search pattern in quotes. if u write
find . -name *.mdwithout the quotes, the shell replaces the*beforefindeven sees it, and u get a confusing error. -
grepandfindbecome much more powerful when u connect them with the|pipe, which we learn in Chapter 8.
Assignment
- Make a dir
ch3-practiceand inside it create a fileanimals.txtcontaining these 4 lines:cat,Dog,bird,cat food. - Find all the lines that contain
cat. - Find all the lines that contain
dog, ignoring the capital letter. - Show all the lines that do NOT contain
cat. - Show the line numbers of every line containing
cat. - From ur home dir, find every file whose name ends with
.txt. - From ur home dir, find every directory whose name starts with
ch.
stuck, or done and want to check? the solutions are here