Welcome to WebmasterWorld Guest from

Forum Moderators: bakedjake

Message Too Old, No Replies

Use of find(1)

A complex tool that has some neat uses



9:48 pm on Jan 30, 2002 (gmt 0)

Inactive Member
Account Expired


satanclaus mentioned "find / -name 'tacos'" in his recent post. I thought it would be a good idea to expand a bit on that so that you can really enjoy the power of find(1).

"find / -name 'tacos'" will return dirs, symlinks, devices, etc. as well as files named 'tacos'. Often you know what type of object you are searching for, so you can add qualifiers to limit your search.

If you want a file, add "-type f" ("-type d" for dirs, "-type l" for symlinks, etc.. see manpage for more details). Also, us oldtimers like to see a trailing "-print", mostly to be pedantic. It's the default action so you can leave it off, but getting in the habit if including it will prepare you for dealing with files that have spaces in the names (more later). So with "-type f" and "-print" added, it becomes:

find . -type f -name 'tacos' -print

Rarely will you need to start with /. If you can isolate where your file is that you're looking for, start there instead. `.' is also quite acceptable (meaning, "start here and go down"). Large environments, like universities, get rather grumpy if they catch you running "find / ...." since it traverses all NFS-mounted filesystems (home directories being the biggest pain). The bigger the search, the longer you'll have to wait for the return. NFS-mounted filesystems will take even longer to walk.

To cover some of the "high-tech" features of find, there are also "-a" for "and" and "-o" for "or". The AND "-a" operator is implied and not required -- "find . -type f -name 'foo' -print" is the same as "find . -type f -a -name 'foo' -print" or "find . -a -type f -a -name 'foo' -a -print". (Starting to see a pattern to the logic?)

The OR -o operator is a little tricky. One way to work with it is to give each side of your -o operator its own -print, like this:

find . -type f -name foo -print -o -type d -name bar -print

One item I find *quite* useful when doing big searches is the -prune operator. My mail is done via mh (nmh/exmh, actually), so I have a .mh dir with literally millions of files in it. When I do a search in my homedir, I do not want find(1) to start digging around in my .mh directory. With -prune, we have a way to tell find(1) to ignore my .mh directory. It goes a bit like this:

find $HOME \( -type d -name .mh -prune \) -o -type f ..... -print

Notice how I had to escape the () pair with the \. That's required since the shell uses () for it's own purposes. We have to tell the shell that we're passing () to find(1) and to leave them alone. (Now you know what the term "escape" means in shell scripting speak.)

On the note of using \( \), it wouldn't hurt to use them with all of your -o operations just to clarify what you want done. The earlier command would then turn into:

find . \( -type f -name foo -print \) -o \( -type d -name bar -print \)

There are a few other flags used with find(1) that I use once-in-a-while. I generally pull up the manpage and tinker with it until it gives me the expected results. Those are "-perm", "-size", and "-user".

Along with find(1), there's xargs(1). xargs is a way of using find to perform actions on a list of files. For example, if you were looking for a file that contained the word "foo" in it, you could type:

find . -type f -print ¦ xargs egrep "foo"

If you have files with spaces in the name, you'll see some errors about not finding files. In that case, you need to use:

find . -type f -print0 ¦ xargs -0 egrep "foo"

(note the "-print0" and then the -0 on xargs(1))

xargs is much better than using find(1)s "-exec <command> {};" feature, since xargs bunches the list of files up into groups of about 256, where "-exec <command> {};" runs your command for every file found. Now that I've talked about it, here's the syntax to use -exec, even though you shouldn't ever use it (I never do):

find . -type f -exec egrep "foo" {};

Hope this helps.

Rob++ (Senior UNIX Sysadmin, at large)

10:08 pm on Jan 30, 2002 (gmt 0)

Senior Member

WebmasterWorld Senior Member 10+ Year Member

joined:Aug 10, 2001
votes: 10

Nice description!
I use the tcsh as my working shell, and there has been an enty in my ~/.cshrc for significantly longer than the www existed:

alias fname 'find . -name "\!*" -print'

This establishes a new command "fname", which can be invoked with a pattern as argument:

$> fname *.pl

lists all Perl files in and below the current directory.
Note that you don't even need to escape the * in this call, as the \!* that expands the argument in the alias definition is already enclosed in double quotes there.

I don't know enough bash syntax to tell you how to define a similar alias there... :o


10:55 pm on Jan 30, 2002 (gmt 0)

Inactive Member
Account Expired


Unfortunately, that is a csh-only trick (the !* use in the middle of the alias).

I dabbled around with defining a function in sh/ksh/bash to do the same thing but quickly discovered that it would be a huge hassle to get it to properly handle the * expansion.

It's interesting that tcsh does not expand any * uses before calling the alias. That behavior is unique to (tcsh's handling of) aliases, which would be rather confusing since it doesn't happen anywhere else in shells.

But yes, what you have works well.

: saturn; tcsh
> pwd
> alias fname 'find . -name "\!*" -print'
> fname *test*
> exit


9:42 am on Jan 31, 2002 (gmt 0)

Senior Member

WebmasterWorld Senior Member littleman is a WebmasterWorld Top Contributor of All Time 10+ Year Member

joined:June 17, 2000
votes: 0

Another excellent tutorial Rob, thanks!
7:13 pm on Jan 31, 2002 (gmt 0)

Preferred Member

joined:Apr 13, 2001
votes: 0

Wow Rob thats the most in depth I've ever seen anyone take find. Very useful as well. I've never put that much thought into my use of find mainly because most of my experience has been w/ relatively small BSD or Linux machines. A great reference. I hope I haven't been making my universities Admin too crazy with my broad searches of his filesystem. :)