|
Softpanorama |
May the source be with you, but remember the KISS principle ;-)
|
Find is actually a pretty tricky utility that is different from any other Unix utility. Still it is one of the most important sysadmin tools. You need to put extra efforts to learn to use it correctly (and still without testing nothing is guaranteed in complex cases ;-).
Find is not only useful for finding files, it is also important for finding directories and can greatly simplify filesystem navigation. See Advanced Unix filesystem navigation and NCD clones for more details (in NCD clones file often used for creation of the list of all directories in mater tree or some sub tree(s) usually stored as gzip archive).
It uses non-standard regular expressions and have a very obscure mini-language to specify your queries. As one Softpanorama reader wrote: "find's syntax is NOT regular, does not recognize standard regex notation, and is arcane, irregular and infuriating."
That's why along with this page we created a mini-tutorial. I hope it can save you some time trying to make your complex find queries work (they almost never worked for me without debugging :-).
There are some interesting options in Posix find (as described in Solaris man page)
|
July 07, 2007 | esofthub.blogspot.com
Find how many directories are in a path (counts current directory)
# find . -type d -exec basename {} \; | wc -l
53
Find how many files are in a path
# find . -type f -exec basename {} \; | wc -l
120
... ... ...Find files that were modified 7 days ago and archive
# find . -type f -mtime 7 | xargs tar -cvf `date '+%d%m%Y'_archive.tar`
Find files that were modified more than 7 days ago and archive
# find . -type f -mtime +7 | xargs tar -cvf `date '+%d%m%Y'_archive.tar`
Find files that were modified less than 7 days ago and archive
# find . -type f -mtime -7 | xargs tar -cvf `date '+%d%m%Y'_archive.tar`
Find files that were modified more than 7 days ago but less than 14 days ago and archive
# find . -type f -mtime +7 -mtime -14 | xargs tar -cvf `date '+%d%m%Y'_archive.tar`
Find files in two different directories having the "test" string and list them
# find esofthub esoft -name "*test*" -type f -ls
Find files and directories newer than CompareFile
# find . -newer CompareFile -print
Find files and directories but don't traverse a particular directory
# find . -name RAID -prune -o -print
Find all the files in the current directory
# find * -type f -print -o -type d -prune
Find files associated with an inode
# find . -inum 968746 -print
# find . -inum 968746 -exec ls -l {} \;
Find an inode and remove
# find . -inum 968746 -exec rm -i {} \;Comment for the blog entry
ux-admin said...Avoid using "-exec {}", as it will fork a child process for every file, wasting memory and CPU in the process. Use `xargs`, which will cleverly fit as many arguments as possible to feed to a command, and split up the number of arguments into chunks as necessary:
find . -depth -name "blabla*" -type f | xargs rm -f
Also, be as precise as possible when searching for files, as this directly affects how long one has to wait for results to come back. Most of the stuff actually only manipulates the parser rather than what is actually being searched for, but even there, we can squeeze some performance gains, for example:
- use "-depth" when looking for ordinary files and symollic links, as "-depth" will show them before directories
- use "-depth -type f" when looking for ordinary file(s), as this speeds up the parsing and the search significantly:
find . -depth -type f -print | ...
- use "-mount" as the first argument when you know that you only want to search the current filesystem, and
- use "-local" when you want to filter out the results from remote filesystems.
Note that "-local" won't actually cause `find` not to search remote file systems -- this is one of the options that affects parsing of the results, not the actual process of locating files; for not spanning remote filesystems, use "-mount" instead:
find / -mount -depth \( -type f -o -type l \) -print ...
- Josh said...
- From the find(1) man page:
-exec command {} +
This variant of the -exec option runs the specified command on the selected files, but the command line is
built by appending each selected file name at the end; the total number of invocations of the command will
be much less than the number of matched files. The command line is built in much the same way that xargs
builds its command lines. Only one instance of â{}â is allowed within the command. The command is exeâ
cuted in the starting directory.- the recursive finds were useful
- " Josh said...
From the find(1) man page:
-exec command {} +
This variant of the -exec option runs the specified command on the selected files, but the command line is
built by appending each selected file name at the end; the total number of invocations of the command will
be much less than the number of matched files. The command line is built in much the same way that xargs
builds its command lines. Only one instance of â{}â is allowed within the command. The command is exeâ
cuted in the starting directory."
Apparently, "-exec" seems to be implementation specific, which is another good reason to avoid using it, since it means that performance factor will differ from implementation to implementation.
My point is, by using `xargs`, one assures that the script / command will remain behaving the same across different UNIX(R) and UNIX(R) like operating systems.
If you had to choose between convenience and portability+consistency, which one would you choose?- instead of using
find ./ -name blah
I find it better to use the case-insentive form of -name, -iname:
find ./ -iname blah- You have to be careful when you remove things.
You say remove files which name is core, but lacks the "-type f" option:
find . -name "core" -exec rm -f {} \;
The same for the example with directories named "junk". Your command would delete any type of files called junk (files, directories, links, pipes...)
I did not know about "-mount", I've always used "-xdev".
Another nice feature, at least in linux find, is the "-exec {} \+", which will fork only once.
Does -prune work like -maxdepth in Unix "find" on AIX?Dave, I purchased your Wicked Cool Shell Scripts book a month or so ago (great book), and have used it to "learn by example" in writing some shell scripts, as I've a long way to go in this area.
I need to rotate logs on an IBM AIX 5.1 Unix box, and tried using your script #55, rotatelogs for this but it didn't work, as -maxdepth is not supported in AIX's find command. So, I commented it out, and it worked, but also rotated everything in the subdirectories as well (no problem...backed up directory first, then restored). I am trying to get it to work using -prune which my search in Google found to be a good fix for the lack of �maxdepth, but it's not doing what I want. Help!
Dave's Answer:
Hmmm... I don't have access to an AIX Unix box, but are you sure that they don't have a copy of GNU find tucked away somewhere on the box? Try using something like find / -name "find" -print as root to see if there's more than one copy of the app on the system.
I'm not sure that -prune is what you want, though. Here's what the find man page on my system says about it:
-prune This primary always evaluates to true. It causes find to not descend into the current file. Note, the -prune primary has no effect if the -d option was specified.
Is this a viable replacement for -maxdepth?
When I run it the output isn't useful:
$ find . -prune -print . $Hmmmm.... replacing the "." with a "*" proves interesting (yes, I'm making the find more interesting too, just matching files that are non-zero in size):$ find * -prune -type f -size +0c -print African Singing.aif Branding for Writers.doc GYBGCH12.doc KF BPlan-04-1123.doc Parent Night.aif Rahima Keynote.aif lumxtiger_outline final.doc master-adwords.pdf $Maybe that's what you need (ignore the specific files I have. You can see what I'm working on as this is my desktop. ;-)Try what I suggested, see what kind of results you get!
How to apply a complex selection of files (-o and -a).
find /usr/src -not \( -name "*,v" -o -name ".*,v" \) '{}' \; -printThis command will search in the /usr/src directory and all sub directories. All files that are of the form '*,v' and '.*,v' are excluded. Important arguments to note are:
- -not means the negation of the expression that follows
- \( means the start of a complex expression.
- \) means the end of a complex expression.
- -o means a logical or of a complex expression.
In this case the complex expression is all files like '*,v' or '.*,v'The above example is shows how to select all file that are not part of the RCS system. This is important when you want go through a source tree and modify all the source files... but ... you don't want to affect the RCS version control files.
Re:pushd and popd (and other tricks) (Score:2)
by Ramses0 (63476) on Wednesday March 10, @07:39PM (#8527252)My favorite "Nifty" was when I spent the time to learn about "xargs" (I pronounce it zargs), and brush up on "for" syntax.
ls | xargs -n 1 echo "ZZZ> "
Basically indents (prefixes) everything with a "ZZZ" string. Not really useful, right? But since it invokes the echo command (or whatever command you specify) $n times (where $n is the number of lines passed to it) this saves me from having to write a lot of crappy little shell scripts sometimes.
A more serious example is:
find -name \*.jsp | sed 's/^/http:\/\/127.0.0.1/server/g' | xargs -n 1 wget...will find all your jsp's, map them to your localhost webserver, and invoke a wget (fetch) on them. Viola, precompiled JSP's.
Another:
for f in `find -name \*.jsp` ; do echo "==> $f" >> out.txt ; grep "TODO" $f >> out.txt ; done...this searches JSP's for "TODO" lines and appends them all to a file with a header showing what file they came from (yeah, I know grep can do this, but it's an example. What if grep couldn't?)
...and finally...
( echo "These were the command line params"
echo "---------"
for f in $@ ; do
echo "Param: $f"
done ) | mail -s "List" you@you.com...the parenthesis let your build up lists of things (like interestingly formatted text) and it gets returned as a chunk, ready to be passed on to some other shell processing function.
Shell scripting has saved me a lot of time in my life, which I am grateful for.:^) [May 16, 2007] Advanced techniques for using the UNIX find command by Bill Zimmerly
Mar 28, 2006 (Developerworks)
Use find creativelyYou can perform myriad tasks with the
findcommand. This section provides some examples of ways you can putfindto work as you manage your file system.To keep things simple, these examples avoid
-execcommands that involve the piping of output from one command to another. However, you're free to use commands like these in a find's-execclause.You can use
findto clean directories and subdirectories of the temporary files generated during normal use, thereby saving disk space. To do so, use the following command:
$ find . \( -name a.out -o -name '*.o' -o -name 'core' \) -exec rm {} \;
File masks identifying the file types to be removed are located between the parentheses; each file mask is preceded by-name. This list can be extended to include any temporary file types you can come up with that need to be cleaned off the system. In the course of compiling and linking code, programmers and their tools generate file types like those shown in the example:a.out,*.o, andcore. Other users have similar commonly generated temporary files and can edit the command accordingly, using file masks like*.tmp,*.junk, and so on. You might also find it useful to put the command into a script calledclean, which you can execute whenever you need to clean a directory.The
findcommand lets you copy the entire contents of a directory while preserving the permissions, times, and ownership of every file and subdirectory. To do so, combinefindand thecpiocommand, like this:
Listing 2. Combining the find and cpio command
$ cd /path/to/source/dir $ find . | cpio -pdumv /path/to/destination/dir
The
cpiocommand is a copy command designed to copy files into and out of a cpio or tar archive, automatically preserving permissions, times, and ownership of files and subdirectories.List the first lines of text files
Some people use the first line of every text file as a heading or description of the file's contents. A report that lists the filenames and first line of each text file can make sifting through several hundred text files a lot easier. The following command lists the first line in every text file in your home directory in a report, ready to be examined at your leisure with the
lesscommand:
Listing 3. The less command
$ find $HOME/. -name *.txt -exec head -n 1 -v {} \; > report.txt $ less < report.txt
Maintain LOG and TMP file storage spacesTo maintain LOG and TMP file storage space for applications that generate a lot of these files, you can put the following commands into a
cronjob that runs daily:
Listing 4. Maintaining LOG and TMP file storage spaces
$ find $LOGDIR -type d -mtime +0 -exec compress -r {} \; $ find $LOGDIR -type d -mtime +5 -exec rm -f {} \;
The first command runs all the directories (
-type d) found in the $LOGDIR directory wherein a file's data has been modified within the last 24 hours (-mtime +0) and compresses them (compress -r {}) to save disk space. The second command deletes them (rm -f {}) if they are more than a work-week old (-mtime +5), to increase the free space on the disk. In this way, the cron job automatically keeps the directories for a window of time that you specify.If you want to copy complex directory trees from one machine to another while preserving copy permissions and the User ID and Group ID (UID and GID -- numbers used by the operating system to mark files for ownership purposes), and leaving user files alone,
findandcpioonce again come to the rescue:
Listing 5. Maintaining LOG and TMP file storage spaces
$ cd /source/directory $ find . -depth -print | cpio -o -O /target/directory
Find links that point to nothingTo find links that point to nothing, use the
perlinterpreter withfind, like this:
$ find / -type l -print | perl -nle '-e || print';
This command starts at the topmost directory (/) and lists all links (-type l -print) that theperlinterpreter determines point to nothing (-nle '-e || print') -- see the Resources section for more information regarding this tip from the Unix Guru Universe site. You can further pipe the output through therm -f {}functionality if you want to delete the files. Perl is, of course, one of the many powerful interpretive language tools also found in most UNIX toolkits.Locate and rename unprintable directories
It's possible in UNIX for an errant or malicious program to create a directory with unprintable characters. Locating and renaming these directories makes it easier to examine and remove them. To do so, you first include the
Listing 6. Locating and renaming unprintable directoriese28">-iswitch oflsto get the directory's inode number. Then, usefindto turn the inode number into a filename that can be renamed with themvcommand:$ find . -inum 211028 -exec mv {} newname.dir \;
List zero-length filesTo list all zero-length files, use this command:
$ find . -empty -exec ls {} \;
After finding empty files, you might choose to delete them by replacing thelscommand with thermcommand.Clearly, your use of the UNIX
findcommand is limited only by your knowledge and creativity.[Feb 9, 2007] Letter to the editor
January 24, 2007 (USA) You have a page with this almost useful command to find ascii files and grep them (omitting binaries, etc):
find . -type f -print | xargs file | grep -i text | cut -f1 -d: | xargs egrep "$*"It works fine, until you go through files like Perl modules which may have some colons in the name. I submit this minor change and introduce another command to your future readers:
find . -type f -print | xargs file | grep -i text | cut -f1 |sed 's/:$//g' | xargs egrep "$*"
It cuts at the tab instead of colon, and then strips any colons out that end the lines without impacting colons in the filename itself. Sneaky, hey?
Kevin
find and xargs
- The first argument to "find" is the directory (or directories) to perform the search.
- Example: find (and display) every file in your home directory:
- find $HOME
- "-name" the name of a file, or a partial name (basic regex).
- Example: find the file named "bookmarks.html" in your home directory:
- find $HOME -name bookmarks.html
- Example: find all files starting with the name "bookmarks" in your home directory:
- find $HOME -name bookmarks\*
- Characters that mean something special to the shell, like the asterisk must be escaped with a backslash or put in single quotes, to avoid problems.
- "-atime/-ctime/-mtime" the last time a files's "access time", "file status" and "modification time",
measured in days or minutes. The time can be compared to another file with "-newer/-anewer/-cnewer".
- Example: find everything in your home directory modified in the last 24 hours:
- find $HOME -mtime 0
- Example: find everything in your home directory modified in the last 7 days:
- find $HOME -mtime -7
- Example: find everything in your home directory that have NOT been modified in the last year:
- find $HOME -mtime +365
- Example: find everything in your home that has been modified more recently than "abc.txt":
- find $HOME -newer klug/find.html
- "-type x" files of a certain type (file, directory, symlink, socket, pipe, block, character) (fdlspbc)
- Example: find all directories under /tmp
- find /tmp -type d
- "-user" files owned by a certain user.
- Example: find all files owned by user "bruce" under /var
- find /var -user bruce
- "-group" files which are a member of a certain group.
- Example: find all files in group "users" under /var
- find /var -group users
- "-size" files of a certain size.
- Size can be specified in blocks, bytes, works, Kilobytes, Megabytes or Gigabytes (bcwkMG).
- Example: find all files in your home directory exactly 100 bytes long:
- find $HOME -size 100c
- Example: find all files in your home directory smaller than 100 bytes:
- find $HOME -size -100c
- Example: find all files in your home directory larger than 100MB:
- find $HOME -size +100M
- "-perm" files that has certain permissions, or has individual bits set or not set.
- Example: find all files in your root directory that are SUID.
- find / -xdev -type f -perm +4000
- Example: find all files in your root directory that are SUID-root.
- find / -xdev -type f -user root -perm +4000
- "-links" files that has a certain number of hard links.
- Example: find all files in your home directory with a hard link count of two:
- find $HOME -type f -links 2
- Example: find all files in your home directory with more than one hard link:
- find $HOME -type f -links +1
- "-inum" a file with a certain `inum`, useful in filesystem debugging and locating identical hard linked files.
- Example: find file with inum=114300 in the /home partition:
- find /home -inum 114300
find can perform a number of actions on the file(s) it finds.
- "-print" prints the names of the files it finds. This is the default if no other actions are specified.
These two commands are identical on recent Linux systems:
- find $HOME -name bookmarks.html
find $HOME -name bookmarks.html -print
- Variations include:
- "-ls" to display detailed output instead of just filename ("ls -dils" format).
- "-fprint" to send the output to a file instead of stdout.
- "-printf" to format the output in a specific way.
- "-fprintf" a combination of the above two.
- "-print0" Same as -print, except it separates files by a null character (ascii 0) instead of a newline.
Although the usefulness of this may not be immediately obvious, it is extremely useful!
See examples below. (the argument ends in the number ZERO, not the letter O)
- Variations include:
- "-fprint0" to send output to a file instead of stdout.
- "-delete" will delete all files it finds. Use with care! :-)
- Example: delete all files named "core" in the /tmp directory:
- find /tmp -type f -name core -delete
- "-exec" will execute any command on the files found.
- Use "{}" to specify the filename found in the command.
- End the command with a ";" (escape it!) to execute the command every time a file is found.
- End the command with a "+" to pass multiple files to the command (like xargs).
- Variations include:
- "-execdir" to execute the command in it's directory (instead of the current directory)
- "-ok" to ask the user for each file found if the command should be executed.
- "-okdir" ask the user and execute in the file's directory.
Other useful find parameters:
- "-xdev" Don't descend directories on other filesystems.
- Useful for searching a single hard drive partition and omitting other HDD partitions, /proc,
CDROM's, network mounts, etc. (network drives and CD's can be really slow to search)
- "-maxdepth n" Descend at most n directory levels. (cannot be negative)
- "-mindepth n" Do not apply tests or actions at levels less than n (non-negative).
- "-daystart" perform time tests from beginning of today, instead of current date/time.
- "-L" follow symbolic links (does not follow symlinks by default).
- "-fstype x" only find files a filesystems of type x.
- Useful for searching hard drive partitions and omitting CDROM's, network mounts, etc.
- "-regex pattern" use full regular expressions.
- Variations include:
- "-iregex" case insensitive regex.
- "-depth" Process each directory's contents before the directory itself
- Useful for removing, since the directory has to be empty before it can be removed
- "-noleaf" Do not optimize by assuming that directories contain 2 fewer subdirectories than their hard link count.
- The default optimization improves speed significantly on Unix filesystems.
However it doesn't work so well on other filesystems (DOS, CDROM, etc.), hence this option.OPERATORS
- "! expr" True if expr is false. (logical NOT)
- "( expr )" Force precedence.
- "expr1 -a expr2" Logical AND (default operation, not necessary)
- "expr1 -o expr2" Logical OR.
- "expr1 , expr2" For different searches while traversing the filesystem hierarchy only once.
Must be used with parenthesis and -fprint to save separate outputs.
Examples:
- Display all jpg files in the top two levels of your home directory:
- find $HOME -maxdepth 2 -name \*jpg -print -exec xv {} \;
- find $HOME -maxdepth 2 -name '*jpg' -print -exec xv {} +
- find $HOME -maxdepth 2 -name '*jpg' -print0 | xargs -0 xv
- cron job to make all files & directories world readable/writable in common area:
- find /somedir/common -type f -exec chmod a+wr {} \;
find /somedir/common -type d -exec chmod 777 {} \;
- cron job to force correct owner/group/permissions on certain files:
- find $BSE/lib/user \( -name '[p,u]*' -a -type f -a ! -perm 664 \) -exec chmod 664 {} \;
find $BSE/lib/user \( -name 'd*' -a -type f -a ! -perm 666 \) -exec chmod 666 {} \;
find $BSE/lib/user \( -type f -a ! -user bsp \) -exec chown bsp {} \;
find $BSE/lib/user \( -type f -a ! -group programs \) -exec chgrp programs {} \;
- cron job to delete some old log files and keep record of files removed:
- find /var/opt/hparray/log -mtime +30 -print -exec rm -f {} \; >> $logf 2> /dev/null
- cron job to delete some old temp files and keep record of files removed:
- find / -name core -type f -fstype xfs -print -exec rm -f {} \; >> $logf 2> /dev/null
find /var/tmp -mtime +1 -name '*aaa*' -print -exec rm -f {} \; >> $logf 2> /dev/null
find /var/tmp -mtime +1 -name 'srt*' -print -exec rm -f {} \; >> $logf 2> /dev/null
find /var/tmp -mtime +7 -print -exec rm -f {} \; >> $logf 2> /dev/null
- Traverse /var only once, listing setuid files and directories into /root/suid.txt
and large files into /root/big/txt. (example taken from the find man page):
- find /var \( -perm +4000 -fprintf /root/suid.txt '%#m %u %p\n' \) , \
\( -size +100M -fprintf /root/big.txt '%-10s %p\n' \)xargs
- Why do we need this "xargs" thing? It's in the presentation title! :-)
Answer: Speed and efficiency.
- The second line runs much faster than the first for a large number of files:
In other words, running "rm" once, with all the filenames on the command line
- find / -name core -exec rm -f {} \;
- rm -f $(find / -name core -print)
is much faster than running "rm" multiple times, once for each file.- However, the second line could fail if the number of files is very large and
exceeds the maximum number of characters allowed in a single command.- "xargs" will combine the single line output of find and run commands with multiple
arguments, multiple times if necessary to avoid the max chars per line limit.
- find / -name core -print | xargs rm -f
- The simplest way to see what xargs does, is to run some simple commands:
- find $HOME -maxdepth 2 -name \*.jpg -exec echo {} \;
- find $HOME -maxdepth 2 -name \*.jpg | xargs echo
- Enter the power of ZERO!
- The 2nd command will fail if any of the files contain a space or other special character:
- find $HOME -maxdepth 2 -name \*.jpg -exec ls {} \;
- find $HOME -maxdepth 2 -name \*.jpg | xargs ls
- Delimiting the file names with NULL fixes the problem:
- find $HOME -maxdepth 2 -name \*.jpg -print0 | xargs -0 ls
- Real world example of a very useful set of commands: (This happens to me all the time)
- Our "webmaster" comes to me and asks if I can "find" all the web pages
that contain the graphic file "ArmstrongISS.jpg" so they can edit those pages.Note: add a "-i" parameter to "grep" for a case insensitive search on the string.
- find /home/httpd \( -name \*.html -o -name \*.php -o -name \*.php3 \) -print0 \
| xargs -0 grep -l "ArmstrongISS.jpg"- The above example alone is worth more than double the price of admission! :-)
Not only does it find files by name, it only displays file names containing a certain string!
When combining "find" with other Linux commands (like grep) and it's potential use in shell
scripts, the power is only limited by your imagination! (and your command line skills). :-)
- Similar examples to demo on my local system:
- find $HOME \( -name \*txt -o -name \*html \) -print0 | xargs -0 grep -li vpn
- find $HOME \( -name \*txt -o -name \*html \) -exec grep -li vpn {} +
Miscellaneous
- Always read the man page for "find" & "xargs" on the system where you plan on using it.
"find" has been around for a long time, but is still evolving at a rapid rate.
- Some arguments are fairly new, and may not exist on some older systems,
and some commercial Unix systems.
- Some parameters, like "-delete" and -exec followed by a plus sign ("+"),
are REALLY NEW. (Neither existed in the SuSE 9.2 "find"!)- Other parameters may be named something completely different on
commerical Unix systems (i.e. "-fstype" == "-fsonly" on HPUX)- Older versions of "find" did NOT have "-print" as the default action.
In fact there was no default, so running find without any action did
nothing noticeable (except use CPU time and grind the hard drive)!
- Always test your commands using "-exec echo" before invoking real commands,
especially destructive commands like removing files! :-)
- Honorable mention: "locate".
- The "locate" package comes with most distributions.
- Installs by default on Redhat/Fedora systems.
- Comes with SuSE, but does not install by default.
- "Locate" consists of a cron job that runs nightly (by default),
and stores all filenames on your system in a searchable database.- Simply type "locate filename" to find the location (directory) of a file.
- Is MUCH faster than using "find" on your entire directory structure, but only
tells you where files live. It has none of the extra functionality of "find".- Using the right tool for the job, "locate" is faster than "find" when you are
only looking for the locations of files (or where they lived as of yesterday).
- Any [more] questions?
- Note to self: if this went too quickly, read the "find" man page out-loud very slowly! :-)
- Fin.
[Aug 23, 2006] A Couple Quick find Tips
* Search and list all files from current directory and down for the string ABC:
find ./ -name "*" -exec grep -H ABC {} \;
find ./ -type f -print | xargs grep -H "ABC" /dev/null
egrep -r ABC *
* Find all files of a given type from current directory on down:
find ./ -name "*.conf" -print
* Find all user files larger than 5Mb:
find /home -size +5000000c -print
* Find all files owned by a user (defined by user id number. see /etc/passwd) on the system: (could take a very long time)
find / -user 501 -print
* Find all files created or updated in the last five minutes: (Great for finding effects of make install)
find / -cmin -5
* Find all users in group 20 and change them to group 102: (execute as root)
find / -group 20 -exec chown :102 {} \;
* Find all suid and setgid executables:
find / \( -perm -4000 -o -perm -2000 \) -type f -exec ls -ldb {} \;
find / -type f -perm +6000 -ls
Note: suid executable binaries are programs which switch to root privaleges to perform their tasks. These are created by applying a "stickey" bit: chmod +s. These programs should be watched as they are often the first point of entry for hackers. Thus it is prudent to run this command and remove the "stickey" bits from executables which either won't be used or are not required by users. chmod -s filename
* Find all world writable directories:
find / -perm -0002 -type d -print
* Find all world writable files:
find / -perm -0002 -type f -print
find / -perm -2 ! -type l -ls
* Find files with no user:
find / -nouser -o -nogroup -print
* Find files modified in the last two days:
find / -mtime 2 -o -ctime 2
* Compare two drives to see if all files are identical:
find / -path /proc -prune -o -path /new-disk -prune -o -xtype f -exec cmp {} /new-disk{} \;[Jul 11, 2006] Linux.com CLI Magic Searching with find
Another useful test is-size, which lets you specify how big the files should be to match. You can specify your size in kilobytes and optionally also use+or-to specify greater than or less than. For example:find /home -name "*.txt" -size 100kfind /home -name "*.txt" -size +100kfind /home -name "*.txt" -size -100kThe first brings up files of exactly 100KB, the second only files greater than 100KB, and the last only files less than 100KB.
What's New in the Solaris 9 4-04 Operating Environment
See Freeware Enhancements for information about GNU grep 2.4.2, GNU tar 1.13, GNU wget 1.6, and Ncftp Client 3.0.3 in the Solaris 9 release.
- GNU grep 2.4.2 is a pattern matcher.
- GNU tar 1.13 is an archiver.
- GNU wget 1.6 retrieves files from the Web by using HTTP and FTP.
- Ncftp Client 3.0.3 uses the File Transfer Protocol. This utility is an alternative to the UNIX ftp program.
Tricks with find by Sandra Henry-Stocker
The two most common options used with find are, not surprisingly, -print and -ls. The -print option prints the name of the file from the point of view of the current directory (e.g., /export/home/sbob/junk.txt or just ./sbob/junk.txt if the search is started in /export/home). The -ls option provides the same type of information that you would see if you viewed the files listings with ls -li.
-execThe -exec option is undoubtedly the next most popular option and is used to specify what should be done with the files that are found. When using the -exec option, the name of each file located by find is represented in the find command with the string "{}" (without the quotes). The command to print the number of lines in each of the files located by find would look like this:
boson> find . -type f -exec wc -l {} \;The \; marks the end of the command and, running this command, you might see something like this:
74 ./04-28-03_CPU_bottleneck.txt 12 ./testme 6 ./testme2 5 ./ixA command to look for particular strings and print the strings and the names of the files in which they would be found might look like this:
find . -type f -exec grep "before" {} \; -printThe -print in this command is put at the end of the command so that the file names are only printed when the selected test was found.
Changing Files with Find
To modify the content of files that are located with find, you might use sed or you might use an in-place Perl command such as this command that runs through all HTML files in or under the current directory to change one URL to another:
find . -type f -name "*\.html" -exec perl -i -p -e \ 's/www.before.org/www.after.com/g;' {} \;If you frequently have to change links on a large web site, a command such as this can save you a lot of time. If you want to provide this command to someone not likely to remember the find command, you can insert it into a script like this:
#!/bin/bash if [ $# != 2 ]; then echo "usage $0" exit else BEFORE=$1 AFTER=$2 fi find . -type f -name "*\.html" -exec perl -i -p -e \ "s/$BEFORE/$AFTER/g;" {} \; Doing Lots with Changed Files
If you want to run a number of commands on each file that you find, there's a way to do that as well - and it doesn't require use of the -exec option. Instead, pipe the output of your normal find command to a while loop such as this and you can run as many commands as you want between the do and done markers.
> find . -type f -print | while read i do file $i ls -i $i wc -l $i doneIn this loop, your file name is assigned to $i. This command should work with shells in the Bourne shell family (sh, ksh, bash and so on).
A lot of work can be accomplished with a cleverly poised find command.
Some of the ideas in this column were provided by Robert D. and Chang A.
Date: Sat, 14 Sep 1996 19:50:55 -0400 (EDT)
From: Bill Duncan <bduncan@beachnet.org>
Subject: find tip...
Hi Jim Murphy,
Saw your "find" tip in issue #9, and thought you might like a quicker method. I don't know about other distributions, but Slackware and Redhat come with the GNU versions of locate(1) and updatedb(1) which use an index to find the files you want. The updatedb(1) program should be run once a night from the crontab facility. To ignore certain sub-directories (like your /cdrom) use the following syntax for the crontab file:
41 5 * * * updatedb --prunepaths="/tmp /var /proc /cdrom" > /dev/null 2>&1This would run every morning at 5:41am, and update the database with filenames from everywhere but the subdirectories (and those below) the ones listed.
To locate a file, just type "locate filename". The filename can also do partial matching. The search only takes a few seconds typically, and I have tens of thousands of files.
The locate(1) command also has regular expression matching, but I often just pipe it through agrep(1) (a faster grep) to narrow the search if I want. Thus:
locate locate | agrep -v man..would exclude the manpage for example, and only show me the binary and perhaps the sources if I had them online. (The -v flag excludes the pattern used as an argument.) Or the binary alone along with a complete directory listing of it with the following command:
ls -l `locate locate | agrep bin`The find(1) command is a great "swiss-army knife" (and actually not that bad once you get used to it), but for the 90% of the cases where you just want to search by filename, the locate(1) command is *far* faster, and much easier to use.
The find command is much more powerful than locate and can be given extensive options to modify the search criteria. Unlike locate, find actually searches the disk (local or remote); thus, it is much slower but provides the most up-to-date information. The basic syntax is as follows:
find directory [options]The most basic usage of find is to print the files in a directory and its subdirectories:
find directory -printAfter learning about the find command, many new users quickly implement an alias or function as a replacement for locate:
find / -print | grep $1Generally, this is a bad idea because most systems have network drives mounted, and find tries to access them, causing not only the local machine to slow down, but also remote machines. To exclude other filesystems during a find run, try using the -xdev option:
# find / -name Makefile -print -xdevThis searches for any file named Makefile, starting at the root directory, but won't search other mounted or network-mounted filesystems, such as NFS (possibly mounted under the /mnt directory). Here's the correct way to get output such as locate from find:
find directories -name name -printFor example, use this line to find all makefiles in /usr/src/:
# find /usr/src -name "[mM]akefile" -printThe -name option accepts all shell metacharacters. An alternative to the preceding method for finding all files named Makefile or makefile is to use the non-case-sensitive -iname option instead of -name. You must use quotation marks to prevent your shell from misinterpreting wildcard characters (such as ? or *). For the truly adventurous, find also supports a -regex option.
In addition to specifying which filenames to find, find can be told to look at files of a specific size, type, owner, or permissions.
To find a file by size, use the following option, where n is the size:
-size n[bckw]The letters stand for:
b 512-byte blocks (default) c Bytes k Kilobytes (1,024 bytes) w 2-byte words For example, use the following to find all files in /usr larger than 100KB:
# find /usr -size 100kTo find files by type, use the following option:
-type xx is one of the following letters:
b Block (buffered) special c Character (unbuffered) special d Directory p Named pipe (FIFO) f Regular file l Symbolic link s Socket Therefore, use the following to find all symbolic links in /tmp:
# find /tmp -type lIn addition to simply printing out the filename, find can be told to print file information by specifying the -ls option. For example, the boldface code produces the following output:
# find /var -name "log" -ls18433 1 drwxr-xr-x 7 root root 1024 Apr 15 11:40 /var/log 391463 3 -rw-r--r-- 1 news news 2632 Apr 16 04:05 /var/spool/slrnpull/logThe output is similar in form to the output from ls -il.
The last option of interest for find is the -exec option, which allows for the execution of a command on each filename that matches the previous criteria. The basic syntax of the -exec option is this:
-exec [command [options]] '{}' ';'The -exec option uses the string '{}' and replaces it with the name of the current file that was matched. The ';' string is used to tell find where the end of the executed command is. For example, the following command line searches each C source code file under the /usr/src directory for the word Penguin, then prints the filename and line number in the file:
# find /usr/src -name "*.c" -exec fgrep --with-filename Penguin '{}' ';'/usr/src/linux-2.2.2/scripts/ksymoops/oops.c:1087: "|(Penguin)"/usr/src/linux-2.2.2/scripts/ksymoops/oops.c:1088: "|(Too many Penguin)"Although you can use the find command to search for strings of text in documents (useful for searching the HOWTOs under the /usr/doc directory), a better use for find is in automating system administration tasks. For example, to regularly search your system for core dumps, you can combine find and the rm command like this:
find / -xdev -name core -exec rm {} ';'This find command line searches the local filesystem and then delete any found core files; it can be used in the system's crontab to recover some disk space used by core dumps
Man pages
Recommended Links
See also Softpanorama Find Mini Tutorial
Find - Wikipedia, the free encyclopedia
Advanced techniques for using the UNIX find command
Finding Files - Table of Contents by David MacKenzie Edition 1.1, for GNU
findversion 4.1 November 1994Find tutorial Copyright 2001 Bruce Barnett and General Electric Company
O'Reilly Network / Finding Things in Unix
One of the most useful utilities to be found on any Unix system is the
findcommand.In the next two articles, I'd like to work you through the syntax of this command and provide you with some practical examples of its usage.About.com: Power Commands- Find
How do I use the solaris find command - ECN Knowledge Base @ Purdue
The Shell Corner Using the Unix find Command
find . -type f -print | xargs file | grep -i text | cut -f1 -d: | xargs egrep "$*"Ed. note: The Windows MKS toolkit K-shell file command identifies Word files as ASCII text with control files. To eliminate these files from the search, I eliminated any resulting files with keyword "control" :
find . -type f -print | xargs file | grep -i text | grep -v control | cut -f1 -d: | xargs egrep "$*"# The above one-liner can be easily modified to other kinds of operations to text files. # # Consider the need to replace all instances of Linux with GNU/Linux.... # find . -type f -print | xargs file | grep -i text | cut -f1 -d: | while read file; do vi $file >/dev/null 2>&1 <<! :%s,Linux,GNU/Linux,g :wq ! done
finda Particular User or Permission# Use for find is locating files belonging to a particular user... # This finds all the files in the current heirarchy belonging to olded find . -user olded -print # or with special permissions... # This finds all root owned suid files. find . -user root -a -perm -4000 -print
findand Backup Files# Use find to perform an incremental backup... consider: find ./ -newer bckup.out -xdev -type f -print | cpio -ocvB >/dev/tape 2>bckup.out # The -newer option only finds files newer than bckup.out... that is, only # files that have been modified since the last backup.а This makes the # command useful for doing incremental backups. # Assuming you are root, and you do this from the / directory, this # should backup up everything on /.а The / is preceded with a "." to # make sure that we can restore the tape to any directory... not just /.Some examples of using Unix find command.
Linux and UNIX find command help
Find and backup
Find can work with cpio, some version of find support options -cpio and -ncpio :
- find . -depth -print | cpio -oB >/dev/rmt0
find . -depth -print | cpio -ocB >/dev/rmt0
which do the same as
find . -depth -cpio >/dev/rmt0
find . -depth -ncpio >/dev/rmt0
findand Backup Files# Use find to perform an incremental backup... consider: find ./ -newer bckup.out -xdev -type f -print | cpio -ocvB >/dev/tape 2>bckup.out # The -newer option only finds files newer than bckup.out... that is, only # files that have been modified since the last backup.а This makes the # command useful for doing incremental backups. # Assuming you are root, and you do this from the / directory, this # should backup up everything on /.а The / is preceded with a "." to # make sure that we can restore the tape to any directory... not just /.
Copyright © 1996-2007 by Dr. Nikolai Bezroukov. www.softpanorama.org was created as a service to the UN Sustainable Development Networking Programme (SDNP) in the author free time. Submit comments This document is an industrial compilation designed and created exclusively for educational use and is placed under the copyright of the Open Content License(OPL). Original materials copyright belong to respective owners. Quotes are made for educational purposes only in compliance with the fair use doctrine.
Standard disclaimer: The statements, views and opinions presented on this web page are those of the author and are not endorsed by, nor do they necessarily reflect, the opinions of the author present and former employers, SDNP or any other organization the author may be associated with. We do not warrant the correctness of the information provided or its fitness for any purpose.
Last modified: March 15, 2008