Showing posts with label find. Show all posts
Showing posts with label find. Show all posts

Thursday, August 23, 2012

Find files modified on certain date or in a date range

When you want to find files matching certain conditions, this is most probably job for the find command. The problem, though, is that you can't specify a certain date.

Options like -atime, -ctime or -mtime receive an argument that specifies the number of 24-hour periods. This means that when you run the following command:

find /usr/log/mysql -type f -mtime -1 -exec ls -l {} \;

you will get not only the files modified today, but those modified within the last 24 hours. You can change this behaviour by adding the option -daystart, which means that the time periods are calculated from the beginning of the current day:

find /var/log/mysql -type f -daystart -mtime -1 -exec ls -l {} \;

This command will produce the list of files modified today. IMPORTANT! Note that the -daystart option must precede all date-comparing options to have an effect.

To find files modified between two dates you can join two conditions using -a option:

find /var/log/mysql -type f -daystart -mtime -3 -a -mtime +0 -exec ls -l {} \;

The result will include the files modified yesterday or the day before yesterday.

Sometimes, though, you may want to specify the dates as they are, not as relative number of days from today. Traditionally, it was done using an awkward technique that involved creating two empty files with modification dates corresponding to the lower and upper borders of the range (using touch -t filename) and then using these files in options -newer and -older:

touch temp -t 200604141130
touch ntemp -t 200604261630
find /data/ -cnewer temp -and ! -cnewer ntemp

(example taken from here)

New versions of find allow you to do just that using -newerXY. Letters X and Y here stand for some one-letter codes corresponding to various comparison types. The combinations are pretty much incomprehensible, but what we need is -newermt. With this option, life gets simple and sunny!

find /var/log/mysql -type f -newermt 2012-08-21 ! -newermt 2012-08-23 -exec ls -l {} \;

This command produces the list of files modified exactly between the beginning of August 21 and the beginning of August 23.

And a little bonus for those who made it to the end! To sum the sizes of the found files (so you can find out, for example, how many gigabytes were written to binlogs in the last two days) use du -c:

du -c `find /var/log/mysql -type f -newermt 2012-08-21 ! -newermt 2012-08-23`|tail -n1

Friday, February 17, 2012

More than one 'exec' action in 'find' command

When you run find command, you can pass the names of the found files to an arbitrary command using -exec option:

find /tmp -mtime +3 -exec rm {} \;

The curly braces get replaced by the name of found files and the command is executed for every file. However, if you want to run more than one command on the file or use the filename more than once in one command, you cannot do that:

Only one instance of `{}' is allowed within the command.

To bypass the limitation, you can execute a shell, passing the filename as an argument. In the commands executed by the shell, the argument will be available as $0:

find /tmp -mtime +3 -exec sh -c 'ls -ld "$0"; rm "$0"' {} \;

Monday, June 27, 2011

Performing more than one search in one pass of 'find'

find is a utility that searches a directory tree for files matching complex conditions. The conditions may include file name, file type, creation/modification time, owner, permissions and others. Besides, you can define an action to be performed on the files that match your search criteria.

When I have to run a number of searches, I usually do it sequentially, but the process may take too much time if the number of files find has to inspect is very large. It turns out that you can define multiple sets of conditions in find and perform different actions on files that match different conditions. The utility will traverse the directory only once.

This is how you can define multiple conditions and actions in one pass of find:

find /data \( ! -group mygroup -exec chgrp mygroup {} \; \) , \
                   \( -type f ! -perm -g=rw -exec chmod g+rw {} \; \) , \
                   \( -type d ! -perm -g=rws -exec chmod g+rws {} \; \)

This command will change group owner for all files that do not belong to mygroup, set read and write permissions for the owning group if the file is a regular file, set read, write and setgid permissions if the file is a directory. All in a single pass.