Finding Stufffinding files on your *nix systemby Mike Peters, February 2004 New users to Linux are often lost as to where they can find files. This article will take you through the various methods you can use to find the files you want. It will show how to search for files according to their name, permissions, size and other criterea. The Linux filesystemThe first thing you should be aware of is the lay out of a typical Linux installation. I'm not go into great detail about the Linux filesystem, just enough to give you a rough idea of what you can expect to find where. Knowing that can help you narrow down your search considerably. Let's look at the / (root) filesystem of a typical setup:
mike@home:~$ ls
/bin /boot /dev /etc /home /lib /mnt /opt /proc /root /sbin /tmp /usr /var
So, what's in these directories? ls - the first port of call
ls [options] [file...]
dir [file...] vdir [file...] POSIX options: [-CFRacdilqrtu1] [--] GNU options (shortest form): [-1abcdfghiklmnopqrstuvwx- ABCDFGHLNQRSUX] [-w cols] [-T cols] [-I pattern] [--full-time] [--show-control-chars] [--block-size=size] [--format={long,verbose,commas,across,vertical,single-col- umn}] [--sort={none,time,size,extension}] [--time={atime,access,use,ctime,status}] [--color[={none,auto,always}]] [--help] [--version] [--] If you have an idea of which directory a file is in, the easiest way to find files is using ls. 'ls' on its own lists all of the files in the current directory. 'ls /some/directory' will list the files in /some/directory. If you want to see the hidden files in a directory use the -a option and if you want to see extended details about files in a directory use -l. For example to show all files and directories in /home/mike use:
mike@home:~$ ls -la /home/mike
Remember, you can use wildcards with ls too. To show all the files in /home/mike with a .html extension:
mike@home:~$ ls /home/mike/*.html
You can use a ? to indicate a single character, so:
mike@home:~$ ls /home/mike/?og.txt
will list the files dog.txt, fog.txt and bog.txt but not frog.txt. Whereas:
mike@home:~$ ls /home/mike/??og.txt
will only list frog.txt. You can also use [] to specify a range. For example:
mike@home:~$ ls /home/mike/[a-d]og.txt
will list files dog.txt and bog.txt but not fog.txt or frog.txt. This is especially useful for files with dates in the name. Say you have a directory of backup files called yyyymmdd_bak.tar.gz (such as 20030425_bak.tar.gz), you can list all files dated between March and August 2003 using something like:
mike@home:~$ ls /backups/20030[3-8]*_bak*
If you want to see only the directories present you need the -d option but beware:
mike@home:~$ ls -d /home/mike/
will only output /home/mike, which can be useful when used with the -l option to see a particular directories details, however, if you want to list all of the directories under /home/mike you need to use:
mike@home:~$ ls -d /home/mike/*/
To see only files, no directories, it's a little more involved:
mike@home:~$ ls -l /home/mike/ | grep -v "^d"
if you only want to see executable files in a directory, use:
mike@home:~$ ls -lF /home/mike/ | grep "\*$"
and finally to see only links you could do:
mike@home:~$ ls -l /home/mike/ | grep "^l"
Finding installed binaries
which [options] [--] programname [...]
In order to find a binary which has been installed in your $PATH, you can use 'which program':
mike@home:~$ which gvim
/usr/local/bin/gvim which will only find files which you have the permission to execute and are in your $PATH. When given no options, which will only report the first executable found, ie the one which would be executed if you just type the command without the path. Use -a to show all matching executables.
whereis [ -bmsu ] [ -BMS directory... -f ] filename ...
whereis will show you the location of an executable, its related source files, libraries and documentation, providing the executable is installed in a 'standard' location.
mike@home:~$ whereis sylpheed
sylpheed: /usr/bin/sylpheed /usr/lib/sylpheed /usr/local/lib/sylpheed /usr/include/sylpheed /usr/share/sylpheed /usr/man/man1/sylpheed.1 /usr/share/man/man1/sylpheed.1 If you only wish to see the location of documentation use the -m option, -b will show only the binaries and -s will show only the sources. Locate
slocate [-qi] [-d
slocate [-i] [-r slocate [-qv] [-o slocate [-e slocate [-Vh] [--version] [--help] locate (or in the case of many distros, slocate), is a search utility which should be present in most if not all Linux distros. It indexes all of the files on your system, providing a fast way of searching for files. If you are using slocate as opposed to the older locate, file permissions are also stored thereby preventing users from seeing files to which they would not normally have access. The advantage of a facility like locate over a command like find (see below), which do a full search of the file system, is that it is much quicker.
mike@home:~$ locate unistd
warning: locate: warning: database /var/lib/slocate/slocate.db' is more than 8 days old /usr/src/linux-2.4.23/include/linux/unistd.h /usr/src/linux-2.4.23/include/asm-sh/unistd.h /usr/src/linux-2.4.23/include/asm-mips64/unistd.h /usr/src/linux-2.4.23/include/asm-parisc/unistd.h /usr/src/linux-2.4.23/include/asm-x86_64/unistd.h /usr/src/linux-2.4.23/include/asm-x86_64/ia32_unistd.h [snip] /usr/src/linux-2.4.24/include/asm-arm/unistd.h /usr/src/linux-2.4.24/include/asm-ppc/unistd.h /usr/src/linux-2.4.24/include/asm-sparc64/unistd.h /usr/share/texmf/include/kpathsea/c-unistd.h /usr/include/sys/unistd.h /usr/include/unistd.h /usr/include/asm-i386/unistd.h There are a couple of disadvantages however. As you can see in the above example, we were warned that our database is over 8 days old. Locate will only find files which have been added to the database. We can get round this problem by making sure we regularly update our database. This can be done by running 'updatedb' on a regular bases, such as from a cron job.
The second restriction of locate is that we can only perform basic searches for files by name. If we want to do a more detailed search we need to use 'find'. Find - the mother of searches
find [path...] [expression]
find will search the directory tree for files according to the rules given. find has the disadvantage that it is much slower than locate but it is a much more comprehensive utility. Most users don't go beyond the basic capabilities of find, but there are a whole host of options availlable. I wont go into all of the options here but just enough to give you an idea of the possibilities available. 'find' on its own will print a list of all files in the current directory. If you want to start searching in a particular directory you can specify the starting directory.
mike@home:~$ find /usr/include -name unistd.h -print
/usr/include/sys/unistd.h /usr/include/unistd.h find: /usr/include/Hermes: Permission denied /usr/include/asm-i386/unistd.h find: /usr/include/ptlib/CVS: Permission denied find: /usr/include/ptlib/unix/CVS: Permission denied find: /usr/include/ptlib/unix/ptlib/CVS: Permission denied find: /usr/include/ptclib/CVS: Permission denied find: /usr/include/openh323/CVS: Permission denied There are a few things to note here. We specify the search path directly after 'find', this is followed by the expression we are searching for and what we want to do with it. As you might expect -name tells find to search for files with the name 'unistd.h' (we could have used -iname to specify a case insensitive search) and -print says to print the result to our console. Actually we could have left off the -print option as this is the default. We needed to give the full name of the file, as, unlike locate, find searches for the exact expression. If we don't know the exact name of the file it's better to use a wildcard expresion. We can also suppress the 'Permission denied' messages by directing error messages to /dev/null using 2>/dev/null (Note: this is not specific to find and can be applied to any command):
mike@home:~$ find /usr/include -iname 'unistd*' 2>/dev/null
/usr/include/sys/unistd.h /usr/include/unistd.h /usr/include/asm-i386/unistd.h find can also be used to search for files according to their last access or modification dates. Find php files in /var/www/html which have been accessed in the last 10 minutes:
mike@home:~$ find /var/www/html -iname '*.php' -amin -10
Same but modified in the last 10 minutes:
mike@home:~$ find /var/www/html -iname '*.php' -mmin -10
To do the same thing using hours rather than minutes you would use:
mike@home:~$ find /var/www/html -iname '*.php' -atime -10
mike@home:~$ find /var/www/html -iname '*.php' -mtime -10 Note here the use of -10 rather than 10. 10 would have searched for files modified or accessed exactly 10 hours/minutes ago. You could also have used +10 to search for files modified or accessed more than 10 hours/minutes ago. If you want to search for files according to their size, find can do that too:
mike@home:~$ find /home/downloads -size +1000k
mike@home:~$ find /home/downloads -size -1000k As you've probably worked out, these commands find files of size more or less than 1000k respectively. Another useful feature of find is to search for files belonging to certain groups or users:
mike@home:~$ find /var/www/html/ -group nobody
mike@home:~$ find /var/www/html/ -user nobody These, and in fact all, find commands can be combined using conditional statements, for example:
mike@home:~$ find /var/www/html/ ! -group nobody
will find files in /var/www/html/ which don't belong to the nobody group. Expanding on this:
mike@home:~$ find /var/www/html/ ! -group nobody -a ! -user nobody
will find files which are not in group nobody and are not owned by user nobody. As you've guessed, ! is equivalent to not and -a equals and (you can use -and also). You can use -o to make or statements such as:
mike@home:~$ find /var/www/html/ ! -group nobody -o ! -user nobody
which will find files not in group nobody or owned by nobody. As I stated earlier, this doesn't just work for -group and -user, you can mix and match options such as:
mike@home:~$ find /home/music/ -iname "*.mp3" -a -user mike -a -size +10000k
to find mp3's in /home/music which belong to user mike and are over 10MB in size. What if we want to find files which have certain permissions, such as world readable or writable files? Well, find can also be used for this with the -perm option. There are basically 3 different ways to use -perm, the first is -perm mode which will find all files which have there permisions set exactly to mode, eg:
mike@home:~$ find /etc -perm 755
secondly -perm -mode finds files with all of thier bits set to mode, eg:
mike@home:~$ find /etc -perm -7
is the same as -perm 777. Lastly -perm +mode will find files where one or more of their bits are set to mode, eg:
mike@home:~$ find /etc -perm +7
If you wish to find all world writable files on your system you would therefore use:
mike@home:~$ find / -perm -2
but this has a problem in that it will also list symbolic links which have permissions of lrwxrwxrwx. To prevent this we can use the -type option:
mike@home:~$ find / -perm -2 ! -type l
this exclude files of type l, which stands for link. Type takes several options the most useful of which are f for file, d for directory and l for links. We can also use symbolic permission modes with -perm. The following example will find all set-user-ID and set-group-ID files:
mike@home:~$ find / -type f -perm -u+s -o -perm -g+s
It can also be usefull to find files on a machine which have no valid user or don't belong to a valid group. The -nouser and -nogroup options do just this:
mike@home:~$ find / -nouser -o -nogroup
Searching on / can take an extremely long time and therefore we often don't want to descend onto mounted files systems, we can restrict the search to the current filesytem by using the -xdev option.
mike@home:~$ find / -nouser -o -nogroup -xdev
The final feature of find which I want to go into is the -exec option. This option will execute a command on the result of the find command. So, for example, you could us ls -lh to list the files found rather than the standard output:
mike@home:~$ find /home/music/ -iname "*.mp3" -a -user mike -a -size +10000k
-exec ls -lh {} \;
Some other examples:
mike@home:~$ find /home/music/ -iname "*dj*food*.mp3" -exec mpg123 {} \;
mike@home:~$ find /var/www/html -iname "*~" -exec rm {} \; mike@home:~$ find /var/www/html -iname "*.php" -exec grep -i foobar {} \; {} indicates to find that it should insert the name of each file returned here and \; indicates the end of the command. I haven't covered all of the options available to find in this article, but, I hope that at least I have given you enough to show you just how powerful a utility find can be. Check the man pages if you want to see all of the options available. ConclusionHopefully you have enough information now to find any file on your system quickly and easily. As you can see, on any *nix system there are many ways to find the file you want, it's just a case of using the right tool for the job. |
Save This Page
|
|


Save This Page