Submit Hint Search The Forums LinksStatsPollsHeadlinesRSS
14,000 hints and counting!

An introduction to the 'find' command UNIX
This is something I wrote in response to the following question on a list:
Could anyone recommend a good command line method (or point me to a previous discussion topic) for globally finding and replacing file ownership? One of our administrators has recently moved on, and I would like to revert ownership of the project files he worked on to the admin user before deleting the user account.
Finding that the find command is often one of the lesser used commands by newbies, here was my response (which I hope others will find useful)...

[Editor's note: Read the rest of the article for some interesting uses and explanations of the "find" command. I modified the formatting of this hint to make it more readable, but the content is as it arrived here.]

Precede the following command(s) with sudo, if required (or use sudo -s to get a privileged shell, first).

To find/replace user ownership (where "foo" is the current user and "bar" is the desired/changed-to user):
 % find / -user foo -exec chown bar {} \;
This says:
  • Do a find (see "man find") beginning at the directory "/" (i.e., the root directory)

  • (find) all files that are owned by the user "foo" (if "foo" was removed from the system/netinfo, in place of "foo," you could use the owner's number that would be displayed by a long listing (ls -l)

  • for each file found, execute/run the program 'chown' (change ownership, see "man chown"), which changes the ownership to the user "bar"
NOTE: the "funny syntax" (that's funny weird, not funny ha-ha) of "{}" says "insert the pathname of the found file" (properly quoted, b.t.w.) and the "\;" is to signify the end of the "-exec" command (actually, the ";" is the terminator and the "\" is to 'escape' it in [have it ignored by] the shell as it would otherwise have meaning to the shell and be 'gobbled up' by the shell, thus breaking the find command)

Now that you understand that much, you're over the hard part! There are many options that allow a myriad of variants to the find command (learn the find command ... it's a serious, capable, many faceted "friend") -- e.g.:
  • find / -group foo -exec chgrp bar {} \; to similarly change group ownership

  • find . -user foo -o -group bar -exec chown fiddle:faddle {} \; to find files, starting in my current working directory, that are owned by user foo *or* (the -o) group bar and change them to be owner/group fiddle/faddle, respectively

  • find . -name "*foo*" -exec chown me {} \; -exec chmod 666 {} \; to find all files named "something / nothing" + foo + "something / nothing" (single or double quotes or "\"s are required if there are special characters [like *] or spaces in the name) then change the ownership to "me" and (executing a second, different command) change the mode to be read/write access for all (see "man chmod")

  • find . -type d -a -user me -exec chmod o-rwx {} \; to find all files of type directory (i.e., all folders) *and* that are owned by the user "me" then run change mode to remove (if present) the "others" permissions for read, write, and execute (well, execute is search permission, if it's a directory)
You should be getting the idea that the find command is very versatile, powerful, useful, etc. (if you're into command-line things, that is). It's syntax is a little nasty, but it's actually worth learning. HINT: when learning (or even after you know enough to be real dangerous), it's often worthwhile to run the command without the -exec(s) *first* to ensure that you're not going to do something you didn't plan on. The command can be interrupted with CTRL-C, so you don't need to let it run to completion, once you see it's doing what you wanted it to.

A note about performance -- each applied "-exec" causes a new process to be run, so expect this to take some time on large numbers of found files. Sometimes there are other ways of doing things that may be blindingly faster. For example, if you want to reset the ownership on a set of folders and all their nested files and folders, doing chown -R foo folder1 folder2 ... will be orders of magnitude faster (and easier) than its find equivalent:
 % find folder1 -exec chown foo {} \
% find folder2 -exec chown foo {} \;
...
find without any qualifying arguments will find everything, recursively. Of course, the find approach can select within that heirarchy of folders. #:-)

Anyway, this is probably much more than you wanted to know (it's the consultant-come-mentor in me, I guess).

Hope this helps (now go lean more about find, chown, chgrp, chmod, as these are pretty useful ... and dangerous!). #;-)
    •    
  • Currently 3.60 / 5
  You rated: 5 / 5 (5 votes cast)
 
[19,604 views]  

An introduction to the 'find' command | 12 comments | Create New Account
Click here to return to the 'An introduction to the 'find' command' hint
The following comments are owned by whoever posted them. This site is not responsible for what they say.
Thank you, thank you, thank you!
Authored by: David on Feb 05, '03 10:46:55AM

I've always wanted to know how to use find, but although I've learned many other Unix commands, it looked a little daunting.

This is going to be GREAT!



[ Reply to This | # ]
O'Reilly's article
Authored by: rootpoot on Feb 05, '03 11:15:47AM
O'Reilly has a great article on the find command.

[ Reply to This | # ]
locate
Authored by: zedwards on Feb 05, '03 11:28:56AM
I have also found find to be dauting (I also use pico instead of vi!) So I use

[shark:~] zedwards% locate foo

to quickly find files. This does not work though if you recently (in the same day) added a file you are looking for (then you just run updatedb as root and wait.

[ Reply to This | # ]
locate
Authored by: kal on Feb 05, '03 11:59:48AM

I don't use "find" that often, so whenever I need to use it with some arguments (e.g. -exec), i need to look it up.

However, for just finding files which match a pattern, I use it in combination with "grep":

find / | grep pattern

Now that I can remember :-)



[ Reply to This | # ]
locate
Authored by: pmccann on Feb 05, '03 06:32:53PM

Gack! That "find" command will take forever!

Try locate (just once) and you'll be hooked: while it won't find
files that you've created/moved since the last database update,
most of the time your searching for stuff that you hasn't moved
recently, and locate will take orders of magnitude less time than
find.

% locate blah

to find all files with blah in the full path

More exotic stuff can be done by piping the output to grep (or even perl):

% locate \\* | grep pattern

(Just set up an alias if this is not easy to remember:

alias myloc "locate \\* | grep \\!* | less"

should do the trick if you're using tcsh.)

But everyone should know that "Locator" (pick of the week a couple of weeks ago)
is a great way to not have to worry about any of this stuff: it puts a nice cocoa skin around the locate+grep combination (actually locate+perl I think, for what it's worth).

Cheers,
Paul



[ Reply to This | # ]
Backslashitis
Authored by: pmccann on Feb 05, '03 06:37:03PM

AAARGH! I hate this thing: preview showed *no* backslashes when I used
a single backslash in those commands, so I doubled them up. Cool, so
preview displays them nicely as single backslashes, just as desired.

So... submit the thing and whaddyaknow: double backslashes and no edit
facility. Bring on the site upgrade! (The forums site has no problems
with such things.)

So just in case it's not obvious: each of the double backslashes in
my previous post should be single.

Sigh...



[ Reply to This | # ]
Backslashitis
Authored by: robg on Feb 05, '03 06:56:53PM

Sucks, doesn't it? Basically, you need two to get one most of the time, but each time you hit Preview, you lose one so you need to add it back. Yech.

The new engine features a [code] tag which leaves EVERYTHING in the tag alone (hooray!). It's also much smarter about handling these special characters, though I'm still not sure it's perfect -- but the mantra will be "use the [code] tag."

-rob.



[ Reply to This | # ]
/usr/libexec/locate.updatedb
Authored by: Numbski on Feb 06, '03 10:18:17PM

no text



[ Reply to This | # ]
zsh does all this!
Authored by: gidds on Feb 05, '03 11:56:39AM
I hope no-one minds me going on about it, but if you use the zsh shell instead of more primitive ones like bash, then the filename completion is so powerful you never need to use find.

For instance, the example above to set ownership of all a user's files, which using find looks like:

    find / -user foo -exec chown bar {} ;
can be written in zsh as
    chmod bar /**/*(u[foo])
Not only is this shorter and easier to write (once you're familiar with the idiom), but it's likely to run much faster as it only launches the chmod utility once, rather than repeatedly for each file.

To briefly explain that cryptic-looking search string: I'm sure you're all familiar with using * in a shell to give a list of all files in a directory.  Well, in zsh you can list files recursively: **/* lists all files in all subdirectories.  So /**/* lists all files starting at the root directory.  The bracketed expression restricts the files returned; in this case, it restricts them to the user `foo'. To restrict them to the current user, you'd simply use (U).

The syntax is extremely powerful: it's easy to restrict files based on filename, time of creation/last modification/access, permissions, size, type, links, with exclusions, ordering, in fact everything find can do and more.  And because it's not in a separate command, you have all the power of the shell in how you use the results.

I'm amazed more people don't use zsh; it's extremely powerful in many other ways too. Not only is it supplied with Mac OS X, but it's open source and available on many other platforms, and is backwardly-compatible with ksh for those who know that. man zsh for more details. You can change your default shell with the NetInfo Manager. (BTW, I have no connection other than as a happy user!)

[ Reply to This | # ]

zsh does all this!
Authored by: Az on Feb 05, '03 08:34:37PM
Hey Gidds

zsh?

Now that's a tip!

Thanks. I think I'll have a look into it - both for my FreeBSD box and my first Mac (12" P-book) when it arrives. Looks great - and simple!

Cheers!

[ Reply to This | # ]

Watch out for precedence of -o
Authored by: sreeves on Feb 08, '03 04:36:36AM

find . -user foo -o -group bar -exec chown fiddle:faddle {} \\;

This doesn't change the ownership of files owned by user foo because the -o "or" operator has lower precedence than the implicit "and" between the -group and -exec, and evaluation stops once the left side of an "or" is known to be true.

You need to use parentheses to force the precedence (and they must be escaped from the shell), like this:

find . \\( -user foo -o -group bar \\) -exec chown fiddle:faddle {} \\;



[ Reply to This | # ]
More backslashitis
Authored by: sreeves on Feb 08, '03 04:39:57AM

Those should all be single backslashes.



[ Reply to This | # ]