The first thing one must do is setup some files to work with for these tutorials. Execute the commands below and we are good to go. By the by, FIND is a command line program that searches for files.
mkdir -p find-test/backup
touch MybashProgram.sh
touch MyCProgram.c
touch mycprogram.c
touch Program.c
cd find-test
for file in ./*; do
cp $file backup/$file
doneSome things to note before we continue. The above will work just fine
but for a curious issue. I use OS X and I learn that
the default file system is case-insensitive while being
case-preserving. This generally is of no consequence in day to
day operations but it does mean that the files we created above will be
missing one entry. Silly stuff eh? One more thing, when we execute any
FIND commands we shall write find but we
will really execute gfind. This is the GNU
version of FIND that is a bit better but for license
purposes cannot be supplied with OS X. You don’t have
to use gfind but some things will not work as they should.
Indeed, the very first example does not work.
The basic usage of the FIND command searching a
specific name : find -name "mycprogram.c". This command
will grab the file in the main folder as well the backup folder.
The same as above but case-insensitive :
find -iname "MYCProgram.c. Try it out and see what happens…
Hmm. Well here’s the thing we get exactly the same thing as we got
before but that’s because of the case-insensitive file system we
mentioned previously. Let’s make one thing clear though : you must be
case-specific when using FIND.
Find the passwd file under all sub-directories starting from
the root directory : find / -name passwd. Sorry about that.
Use sudo to sort out the ‘permission denied’ errors but
really you shouldn’t run this command on a regular basis. To limit our
search to the root dir and one level down try this :
find / -maxdepth 2 -name passwd. Play around with other
maxlevels. You can specify a range of depths like so :
find / -mindepth 3 -maxdepth 5 -name passwd.
The following command checks the MD5 checksum of the
found files. The curly braces are replaced by the file name :
find -iname "mycprogram.c" -exec md5sum {} \;.
Match files that do not match the supplied term :
find -maxdepth 1 -not -iname "mycprogram.c".
Every file has an unique inode number and we can use that to identify
files. Create two files with the same name but add a space to the end of
the second file. Use quotes to make this happen. Use ls to
verify the two files : they look the same no? Try this instead
ls -i1 test* and one can see the inode number by
each file. We can specify an inode number as part of our
FIND command :
find -inum 4120262 -exec mv {} new-test-file-name \;. Bear
in mind that the number I’ve provided was the specific number I got from
the list command. The number you get will be different.
Run ls -i1 *test* to prove the command worked. Use this
command when there might be ambiguity or poorly named files.
You can find files based on their permissions which could prove
interesting perhaps combined with the -not flag.
find . -perm -g=r type f -exec ls -l {} \; the command
searches the current folder for files (type -f) with read
permission to ‘group’. To find files which has read permission only to
group try this for size :
find . -perm g=r type f -exec ls -l {} \; or to do the same
thing using octal numbers
find -perm 040 -type f -exec ls -l {} \;.
One can use the -empty flag to find zero byte files. To
find all liked-minded files in the home directory :
find ~ -empty. Probably a good idea to limit that search :
find. . -maxdepth 1 -empty. Lastly, let’s search for
non-hidden, zero-byte files in the current directory
find . -maxdepth 1 -empty -not -name ".*". Lovely.
Keep in mind that this command might take a while to run depending on
which folder/files you choose to search. Big files :
find . -type f -exec ls -s {} \; | sort -n -r | head 5,
small files :
find . -type f -exec ls -s {} \; | sort -n | head 5. The
second command will yield a bunch of zero byte files. An alternative you
could use is :
find . -not -empty -type f -exec ls -s {} \; | sort -n | head -5.
Find only socket files : find . -type s, find all
directories find . -type d, find only ‘normal’ files :
find . -type f, find all the hidden files
find . -type f -name ".*", find all the hidden directories
find -type d -name ".*".
Show files which have been modified after the specified file. The
following command lists files by date : ls -lrt. Try this
out and pick a file…do you have one? Now with the file you have in mind
try this command out find -newer $FILE. You should get a
list of any file that is, unsurprisingly, newer than the supplied
file.
find ~ -size +100M will give you any file above 100M in
the home directory. The following suffixes can be used :
The + symbol means greater than, - means
less than and no symbol is equivalent to.
There are two options for modification time : -mmin n
and -mtime n. The former searches for file’s modified ‘n’
minutes ago while the latter searches for the same thing but ‘n’ * 24
hours. An example : find . -mmin -60 will find all finds in
all subdirectories that have been updated within the last hour.
find / -mtime -1 will search for all files modified
within the last 24 hours.
Similar to the above we can search for access time rather than
modification. We do this using -amin n and
-atime n which operate exactly the same as the modification
searches. Some examples : find -amin -60 &
find -atime -1 operate as above but based on access time
rather than modification time.
The same as the above two but with the flags -cmin n
& -ctime n.
One can search for files based on the modification of another file.
This could prove useful to use a file as a milestone.
find -newer /etc/passwd will find any files modified after
‘etc/passwd’. On a similar note, one can find files that have been
accessed after the modification of a particular file :
find -anewer /etc/hosts. Lastly the same thing will of
course be true of changed files : use the -cnewer flag to
find files changed after another files modification.
As we’ve seen with some previous examples, you can use the
-exec flag to run external commands on the results of the
FIND command. A simple example might be to list the
FIND results in a different format :
find -mmin -60 -exec ls -l {} \;.
The issue with searching from the root (‘/’) is that it will search
through ‘/Volumes/’ which might contain mounted network shares and
external hdds. The flag -xdev will search the current file
system but no others, handy!
The ‘{}’ braces are a stand in for the files that have been found : a
variable. You can use the braces more than once in a command :
find -name "*.c" -exec cp {} {}.bak \;. This command will
find any file with a ‘c’ extension and copy it with ‘bak’ extension
added on.
While it’s pretty important to see any errors that crop up you might
not want to see them (?). In any case you might have seen a couple of
‘Permission denied’ that may well annoy you so let’s suppress :
find / -name "*.conf" 2>>/dev/null. Just remember
that annoying error messages are there for a reason…