Skip to main content

grep-vs-find

There is no universal argument order for all CLI commands. Each command defines its own grammar.

grep [OPTIONS] PATTERN [FILES...]

Works
grep -ri usemediaquery --exclude-dir=node_modules .
Because GNU grep allows options even after the pattern, as long as they are unambiguous.
GNU tools are very forgiving.

some older systems wont work. Safe example
grep -ri --exclude-dir=node_modules usemediaquery .

grep -ri -- "-test" .
-- means stop parsing [OPTIONS]

-r Recursive
-R Recursive + follow symlinks
-n Show line numbers
-i Case insensitive
-l Show filenames only

find [WHERE_TO_SEARCH] [CONDITIONS] [ACTIONS?]

find . -name "\*.log" -delete

find . -name "\*.ts" -exec grep "useMediaQuery" {} \;
{} → placeholder for current file
\; → ends the command


Pattern 1: Most tools follow
command [OPTIONS] [OPERANDS]
e.g. grep, ls, cp, mv, rm

--

Pattern 2: Subcommand Style
command SUBCOMMAND [OPTIONS] [ARGS]
e.g. Git, Docker, npm

git commit -m "msg"
docker build -t app .
npm install express

--

Pattern 3:
Expression-Based
find . -type f -name "\*.js"
awk '{print $1}' file.txt
e.g. find, awk


in find: -type f -name "\*.ts" (CONDITIONS)
looks exactly like
in grep: --exclude-dir=node_modules (OPTIONS)

Just because something starts with -
does NOT mean it is an “option”.
The dash is just a convention.
What matters is:
How the program chooses to interpret it.

grep -ri --exclude-dir=node_modules "test" .
Everything starting with - modifies how grep behaves.
-r → recurse
-i → case insensitive
--exclude-dir → ignore some directories
These do not describe what to search.
They describe HOW to search.

find . -type f -name "_.ts"
Here:
-type f
-name "_.ts"
These do NOT configure find.
They describe the filter logic.
They are part of the search expression.
Huge difference.

grep CONFIGURATION PATTERN FILES
find PATH FILTER_EXPRESSION

The -type and -name are not configuring find.
They are building a logical test.


Original Unix (1970s)
short options, single letter
ls -l
rm -r
grep -i

If an option needed a value
-option value
find . -name "\*.ts" -name = option/predicate

tar -f archive.tar

GNU Arrives (1980s–1990s)
--long-option
Two dashes = long option.
e.g.
grep --ignore-case
grep -i

then they added support for = (equal sign)
grep --exclude-dir=node_modules

This was syntactic sugar for:
grep --exclude-dir node_modules

The equals sign is optional in most GNU tools.

You can still write:
grep --exclude-dir node_modules
The = is optional.
The equals sign is just convenience.

-a → old Unix short option
--all → GNU long option
--option=value → GNU convenience syntax
find -name → expression token, not configuration flag

find has
Expression Predicates (find)
find . -name "*.ts"
-name does NOT configure find.
It is part of the search expression.
It evaluates to:
TRUE or FALSE for each file

find has three kinds of things after the path:
Tests (predicates)
-name, -type, -size
Actions
-print, -delete, -exec
Operators
-o (OR), ! (NOT), parentheses

find . -type f -name ".ts"
parsed as
(type == file) AND (name matches "
.ts")

Modern replacements for find already exist.
fd --type f --extension ts


short flags -a -l

"long" flags in old times
-name "*.ts"
-type f

Single dash + word.
These were basically predicates or expressions (like find) — not configuration flags in the modern sense.
⚠️ This style is mostly legacy. Modern CLI design avoids it.

Modern CLI Conventions
Short -d ls -l
Long --directory ls --directory

Single letter → single dash (-a)
Full word → double dash (--all)
Never a single dash with a full word in modern commands (-all is discouraged / invalid)

One dash + full word (-type, -name) is basically a historical artifact, like in find.

Option / flag → changes behavior of the program
Predicate / test / filter → describes WHAT to operate on, not HOW

Modern commands, for predicates
uses double-dash style flags for predicated
fd --extension ts --type f

could also be this ...
mini-language (predicate expressions)

jq (JSON predicate tool)

jq '.items[] | select(.active == true)'


Legacy:
Single dash + word: -name, -type → could be predicate or configuration flag.
No easy way to tell without reading the man page.

So in legacy Unix tools, dash style ≠ semantic meaning. You just have to know the command.

Modern:
Usually short flags are only configuration flags, rarely predicates.
predicates usually have arguments like --name=jack

in modern tools there's no way to know by looking at it whether it's a predicate or configuration flag. You just have to know
Because both use --sth

configuration flags can have arguments
grep --color=auto "foo" file.txt


git commit -m "some message"
PartTypeExplanation
gitCommandThe program you’re running (CLI tool).
commitSubcommandTells git what action to perform.
-mShort flag / configuration optionConfigures the behavior of git commit.
"some message"Argument to the flagThe value for -m. Specifies the content, not what files are selected.