find command with -exec

Hi all,

Please could someone help with the following command requirement.

I basically need to find files NEWER than a given file and order the result on time.

My attempt so far is as follows:

find . -newer <file_name> -exec ls -lrt {} ;\

But I dont seem to get the right result and more files are returned.

Any ideas?

Thanks in advance,

jd

Which operating systems and shells (include version numbers for both) must the solution support?

Regards,
Alister

linux or solaris

You can invert -older with !. This ought to work on both. It would also include files equal in date though.

find . '!' -older reference-filename ...

its the -exec ls -lrt \;

that I have a problem with. The files are not being ordered by date.

Any ideas?

I wondered why you were giving it ls -l, but it didn't occur to me... Well, they're not being ordered by date because find executes ls 99,999 times for 99,999 individual files here. Sorting a list one file long just leaves you where you started.

Try '+' instead of ';', which should feed as many files into ls as it's able.

Unfortunately, if there's thousands and thousands of files, it may have to split the list into multiple chunks, so it would end up not sorted by date again.

I believe Solaris find has this feature but am not 100% positive. If it doesn't, something may have to be kludged with xargs for roughly the same effect:

find ... | xargs ls -lrt

This will not work if any of the filenames have spaces or quotes in them.

Your code executes ls for each file that is newer than the file named by <file_name> and if one of those files is a directory, you'll list the contents of that directory instead of the directory itself.

I think you want something like:

ls -lrt | awk -v file=<file_name> 'BEGIN        {found=0}
        found==1        {print}
        $9 == file      {found=1}'

Note, however, that this will not work if the file name indicated by <file_name> contains any whitespace characters or if any filename older than that file has a name that starts with that name and is immediately followed by a whitespace character. I assume you can work around this limitation.

find . -newer <file_name> -exec ls -1ad {} \+

works fine.

Thanks!

Hi

By the way, you can't use -exec ls -lrt to sort the find output, because ls will be called for each file, so it will only sort the given file.

You should sort after the find process, maybe you could use something like find ... -printf "%T@ %p" , and then use sort -n on the output.

I'm not sure whether sun find supports -printf in that way. You need to not rely on extensions when using Solaris.

You are right i forgot about those Solaris limits.

Maybe this should work then :

find  . -newer filename -exec perl -e "\$fname=\"{}\";"'$mtime=(stat($fname))[9]; printf("%ld %s\n",$mtime,$fname);' \; |
  sort -n |
  awk '{print $2}'

If perl is going to be used, there's really not much point in using find, sort, or awk. Perl can traverse directory trees, sort lists, extract fields, etc.

The following may be of interest:
http://perldoc.perl.org/File/Find.html

A similar, more efficient approach to your suggestion would be to -exec stat ... . GNU and solaris both provide a stat utility, but they require different options to accomplish the same task. Before calling find, the script can test the platform to choose between the two syntaxes.

Regards,
Alister

This works fine as long as you either have a small number of files OR don't care about a long list of files that isn't sorted.

Note also that you can just use "+" instead of "\+"; you need "\;" instead of just ";" because an unescaped <semicolon> is special to the shell.