find . | grep user
and find . -path "user*"
do two quite different things. They might seem like they're the same, but they're not.
I'll mention the two most obvious differences first just to get them out of the way. The first is that you'd need to use -path '*user*'
to get exactly the same result as the grep user
..this isn't very important. The second, slightly more important obvious difference is that running two processes when one will do is inherently less efficient (in terms of CPU and RAM usage) - a more significant efficiency than saving two keystrokes.
The real difference, though, is what you can easily do with the filenames found by find
itself, and those found using grep
. Like most command line utilities in linux/unix, find
is a very flexible tool - it's capable of a lot more than just finding files and printing their filenames.
With the pipe to grep, what you have is just a text list of filenames matching a particular pattern.
If you've used A NUL character as the filename separator rather than just a newline (w.g. with find's -print0
action and GNU grep
's -z
aka --null-data
option), you can safely pipe it into xargs -0
(or perl
or awk
or any other program that can take NUL-separated input) and process the files.
e.g. using du -sch
as a very simple example:
find . -print0 | grep -z user | xargs -0r du -sch --
If you didn't do that, or if your version of grep
doesn't support -z
then you can only safely process your filenames if a) you use a newline as filename separator and b) you are absolutely certain that none of the filenames will contain a newline (newlines are valid in filenames - annoying but true, and something you occasionally have to deal with).
find . | grep user | xargs -d '\n' -r du -sch --
Both of these use 4 processes (find, grep, xargs, and du) in a pipeline to total disk usage of the filenames.
With find
, however, you can use the -exec
or -execdir
options to directly process the filename without needing to care about what delimiter you're using.
e.g.
find . -path '*user*' -exec du -sch -- {} +
This uses 2 processes (find and du) to achieve the same result.
The second real difference (and this is a big one) is that while grep
can only select files by matching a regex pattern against each file's name, find
can use each file's metadata to filter out unwanted matches (or to select only very specific matches - same thing)
Some examples of what find
is capable of:
If you want only regular files, use -type f
, if you want only directories, use -type d
, symlinks -type l
and so on.
If you want only files owned by a particular user, use -uid nnn
or -user username
..same for -gid nnn
and -group groupname
.
find
can match on permissions, on timestamps, on size, and on whether a file is -readable
or -writable
by the user running it.
It also has built in regular expression matching (-regex
, with a choice of regex styles using -regextype
), as well as glob matching (-name
, -path
).
You can use -prune
to exclude entire subdirectory trees from being searched (reducing the amount of disk i/o and time required).
It can combined all of these with boolean logic operators AND, OR, and NOT.
find
also has various built in actions. The default is -print
, and I've already mentioned -print0
. It can also output any of the available metadata of a file in whatever format you want with its -printf
action. It can delete files with -delete
, or output a detailed list (similar to ls -l
) with -ls
.
-exec
runs any external process and gives it the list of matching files on the command line with {}
. Either one file at a time if you terminate the -exec
command with \;
or as many as will fit into a shell command line at a time with +
.
-execdir
does the same but, if using \;
changes to each file's directory before running the external process. With +
it changes to the directory and then runs the external command with as many filename arguments as will fit on a command line.
BTW, some of the above find predicates and actions are GNU extensions, and may not work in other non-GNU versions of find
.
find .|grep user
would be more likefind . -path '*user*'
. – Stéphane Chazelas Mar 05 '18 at 12:28ls user*
(8 chars typed)? – Philippos Mar 05 '18 at 12:34find
andgrep
is that when you need a precise complexe patern to match like*someT*hing_*
Then usingfind | grep
is way faster thanfind -name
I personnaly don't care bout length of a command as soon as it works fast. – Kiwy Mar 05 '18 at 12:39find .|grep user
is two less characters typed. – Nick Gammon Mar 06 '18 at 04:55find |grep string
– Hopping Bunny Mar 07 '18 at 04:43