![]() |
| |||||||
|
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Now Where Did I Put That File? - locate To paraphrase Douglas Adams: The file system is big, very big. You may think your home directory is big, but that's just peanuts compared to the whole file system. Just like the Finder (or Sherlock pre-10.2), the command line provides a means to root out files given a description of some sort. First we have 'locate'. locate "*.txt"will find all files ending in '.txt'. And it'll do it quickly. 'locate' uses a pre-built database which contains the names of all files in the file system. If 'locate' does not work, it means the database has not yet been built. It is built weekly at 4:30 am on Sunday - if you have your machine up and running at that time. To (re-)build the database type: % sudo /usr/libexec/locate.updatedbThis will take a minute or so, and you will have to enter your admin password. When the prompt returns, try the locate command again. You should now be able to locate files anywhere on the file system. There are a few important points to note in order to use 'locate' successfully. 'locate' matches against the whole pathname, hence: % locate "bio.*"will not locate the file bio.cwk (or rather the file '/Users/me/Documents/bio.cwk'), but %locate "*bio.*"will. Remember to enclose the filename in quotes if it contains wildcards, otherwise the shell will interpret the '*' passing the filename expansion to 'locate'. However, if one passes a filename with out any '*', it is treated as if it starts and ends with a '*' % locate bio.is equivalent to % locate "*bio.*"A Teaser If your current working directory has a file called 'bio.cwk', then the command: % locate bio.*will locate bio.cwk, and perhaps other files like mybio.cwk. This may appear to contradict what I said above, but it doesn't. Can you think why? |
Tell Me More...
|
|
Wildcards You can make use of the wildcards covered in Part 3 - * ? [] - as part of the filename. It is essential to enclose the filename in quotes if it does contain wildcards to prevent the shell from expanding them before executing 'locate'. The Locate Database The locate database is updated by the Unix housekeeping scripts run periodically by 'cron'. 'cron' is a system program that runs every minute and reads a special file - '/etc/crontab' - that controls what is done and when. Mac OS X has three scripts that run daily, weekly, and monthly. Script 'weekly' in '/etc' updates the locate database. If you want the Unix housekeeping daily, weekly, and monthly scripts to run (which is generally a good idea) you have several options:
or... Mac Janitor Install MacJanitor from Brian R Hill. This runs the three maintenance scripts for you. |
Now Where Did I Put That File? - find
'find' is similar to locate, but it does a live search of the file system. The search will necessarily be slower, but does not rely on a potentially out of date database.
The real power behind 'find' lies in the way one specifies which files to locate, erm I mean find. One can search against just about any property of the file, not just name.
The (simplified) syntax of the find command is:
% find [options] starting-directory [search-criteria] [action]'find' is recursive in that it searches the entire directory structure from 'starting-directory' down. It considers each file and directory selecting those that satisfy 'search-criteria', and performing 'action' on that file. The search-criteria can specify files by name, modification time, size, file attributes, and users/groups/permissions. Search criteria can be combined with 'and' and 'or' conditions. The actions can display the file (the default), list it, delete it, or execute any other command.
Note: 'find' is a very complex and powerful command. It is covered in more detail in a forthcoming advanced lesson. In this tutorial we will consider just name, time, and size criteria.
% find .simply lists all the files and directories from the current (specified by the '.') directory down.
Note that if one searches the entire file system, it is necessary to do so with root permissions, and hence to use 'sudo'.
|
The search criterion '-name' allows you to search for files by name. To find all files named with a '.txt' extension use: % find . -name "*.txt"The search criteria:
The elasped time is calculated from the point at which 'find' was executed, and rounded up to the nearest minute or day. To find all files modified in ~/Sites three days ago: % find ~/Sites -mtime 3and 10 minutes ago: % find ~/Sites -mmin 10A time specified by -n means less than, while +n means more than. To find all files in you home directory modified within the last week use: % find ~ -mtime -7Finally, the criterion 'newer' allows one to specify a file as the time. All files that are newer than (modified after) the given file will be found. For example: % find ~ -newer last-backup.logwill find all files changed (or created) since last-backup.log was modified. The search criterion:
specifies a size in half-k (512 byte) blocks. As with the time criteria, the value of 'n' can be preceded by + or - to specify larger than or smaller than. To find all files that are larger than 2 megabytes (4000 of these 512 byte blocks): % find ~ -size +4000You can guess how to find empty files. However, this will not work when finding empty directories, as an empty directory does not have a size of 0. (All directories contain the '.' and '..' links). To find all empty files and directories use: % find . -empty'find' is able to perform a few actions on each file that satisfies all the search criteria. These are:
To give a long list of all '.doc' files in your home directory, combine find by name with action 'ls' % find ~ -name "*.doc" -lsYou can guess how the '-delete' option works. Obviously be careful with this one. You can also execute any other command on each file found using '-exec'. For example, to display all '.txt' files in your home directory, we can use 'cat' on each file. % find ~ -name "*.txt" -exec cat {} \;The '{}' element of the command is a placeholder for the currently found file. It is replaced by the filename of the current file. The exec action must finish with a ';' character. The reason for the '\;' combination is to stop the shell seeing the ';' first. Another example - add execute permission to all shell script files (those ending in '.sh' in this example). % find . -name "*.sh" -ok chmod a+x {} \;Here I have used the '-ok' action. This is the same as '-exec' and additionally asks for confirmation before the command is executed on each file. The Find Depth Modifier The command: % find . -maxdepth 2will find all files in the current directory, but will only search nested directories up to the specified maximum depth. Remember to use: %man findto learn more about 'find'. |
Tell Me More...
|
|
Wildcards You can make use of the wildcards covered in Part 3 - * ? [] - as part of the filename given to '-name'. It is essential to enclose the filename in quotes if it does contain wildcards to prevent the shell from expanding them before executing 'find'. Access, Change, Modify 'find' uses one of three timestamps when finding by time. Access time: use '-amin' or '-atime' Change time: use '-cmin' or '-ctime' Modification time: use '-mmin' or '-mtime' More Shells - the c-shell 'csh' is the c-shell ('c' is a programming language). It is a good interactive shell, and has a scripting language that looks like 'c' language programs. However, it is not upward compatible with 'sh' and (according to many people) is flawed as a scripting shell. The t-shell 'tcsh' is an improvement on 'csh'. It is a very good interactive shell and improves greatly on the scripting of 'csh'. And More... Others are the z-shell ('zsh') which is very powerful interactively and can run 'sh' scripts, and the korn shell, of which I know little. All but the korn shell are included with Mac OS X as of 10.2 I would have preferred Mac OS X to use 'bash' as the default shell for two reasons:
The problem with 'tcsh' is that one has to lean two scripting languages - 'sh' and 'tcsh'. Running Another Shell Type: % shto work within a Bourne Shell, and % exitto exit the shell. |
Next Part
In Part 6 I will introduce piping - directing the output of one command to form the input of the next command thus chaining a small number of commands together - an essential technique in harnessing the power of the command line and Unix tools.
I will also introduce the 'grep' command, which searches within files, and in Part 7 the 'sed' command, which changes the contents of files.
Until then, have a play with 'find' and get used to using it.
Enjoy :-)
Discuss this article in the Learning Center forum
|
|
Part 5 - Working With Unix (page 2 of 2) |
|