Monday, August 10, 2009

Finding files in Linux / Unix

I have a lot of friends and colleagues who ask me about searching files in unix. Most of them are web-developers and graphic designers, who are typically not from the Unix world and are intimidated by the console world. This blog is mainly for them.

find is a very powerful command, the only problem is figuring out how to use it to get the result you want. In its simplest form, the syntax of find command looks like this:

$ find path parameters/operators

path is the path where you want to search for the files, and parameters/operators are usually the criteria on which you want to find the files eg: name, date etc.,

most common form of find command would be as below:

# find / –name Downloads

The above command will search the complete filesystem for a file/folder named “Downloads”

The other options that are available are

find –name filename find the file filename
find –perm mode finds the files based on the permission/access mode. Access mode here has to be specified in octal viz., 640 etc.,
find –type c finds files based on the filetype, viz.,
b for block special files
c for character special files
d for folders or directories
f for plain files
l for symbolic links
p for Named pipe files
s for socket files
find –name username find files owned by the user <username>. username can be specified as UID
find –group groupname find files owned by the group <groupname>. groupname can be specified as GID
find –size n find files by their size. n  denotes blocks. each block is 512 bytes. +n can be used to look for files larger than n blocks.
find –atime n


-
mtime n

-ctime n
find files last accessed n days ago. to make this command even more powerful, you could use –n to say files accessed less than n days ago.

same as –atime, except that it looks for content modified time

same as –atime except that it looks for access mode changed time
find –newer file finds files that have a modified time stamp that is more recent than the file specified
find operator1 –a  operator2 find files that match operator1 and operator2. this is the default behaviour when two operators are specified, so –a is optional
find operator1 –o operator2 find files that match operator1 or  operator2
find !operator find files that do not match operator
find \{expression \} find using regular expressions…very complex and powerful
-print prints the output to standard output ie., console
-exec command executes the command. command must end with \; as shown in the example below:
# find –name “*.mp3” –exec rm –rf {} \;
the above command will search for files with extension “.mp3” in the current folder and delete them.
{} in the above command will ensure that the complete path of the file is passed onto the command.
-ok command works exactly like –exec command, except that in this case, it prompts the user before executing the command

Some examples:

$ ls –l `find . –type l -print`

find . –type l –print in the above command will print all the symbolic links in the current directory. –print will print it to standard output, in this case, it is being redirected to ls –ld, which in turn will print them in a long listing format.

$ find . –atime 4 –print

will find files that were last accessed 4 days ago

$ find . –mtime 7 –print

will find files that were modified 7 days ago. You also specify a range of time.

$ find . –mtime 7 –mtime –9 –print

will find files that were modified between 7 to 9 days ago.

If you wanted to delete all the files in the current directory and sub-directory that have not been accessed in 90 days, then you would use the command below:

$ find . –atime +90 –exec rm –rf {} \;

pretty powerful isn’t it. you could also tweak this command to delete only the log files like *.log or *.tmp easily.

$ find . –atime +90 \(–name “*.log” –o –name “*.tmp”\) –exec rm –rf {} \;

Combining GREP and FIND

If you wanted to search for a particular word in all the files of a particular directory, then you could do a command substitution with grep as below:

$ egrep ‘findme’ `find . –type f -print`

 

There is a lot more we could do by combining the power of find with other commands. We barely scratched the surface here.