Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

When I deploy my software, I ship a zipped file to the target server and extract it's contents. In addition to this, at the same time I also place a metadata file in the directory, detailing what was deployed.

If I want to find any files that have been changed since I deployed the software, I can simply find files that have a new modification time than the metadata file:

find . -newer deployment_metadata.txt

That's nice and straight-forward.

Now, I'd like to also find files that are old than the deployment metadata file. One would assume you could use the bang symbol to negate the "newer" check

find . ! -newer deployment_metadata.txt

But this actually find all the files that were deployed. Because 'not newer' is not equivalent to 'older', as any files with the same timestamp are by definition "not newer" - they're the same!

So, I was wondering if I was missing a trick when it comes to finding (strictly) old files?

My current solution is to create a new file (in the temp dir) using touch which has a modification time of one minute before the deployment_metadata.txt file. Then I am able to use the following arguments: ! -newer /var/tmp/metadtata_minus_1.

This works, but seems like a waste of time to have to create, and then clean up, the file in the temp dir - especially as different users may be using my script to check for this (don't want file ownership problems, so I actually go as far as appending ${USER} to the filename.

share|improve this question
1  
Not sure if it's going to make much difference, but I should have really attached the version of find I'm using find --version GNU find version 4.2.27 Features enabled: D_TYPE O_NOFOLLOW(enabled) LEAF_OPTIMISATION SELINUX –  jwa Aug 22 '13 at 10:16

2 Answers 2

up vote 1 down vote accepted

One way is to (ab)use epoch time. Here is a test run where I first create seven files in sequence in an empty directory, where the c# files get "the same" ctime as far as find will be concerned:

$ for i in a b "c1 c2 c3" d e; do touch $i; sleep 1; done
$ find -newer c2
.
./d
./e
$ find -not -newer c2
./c3
./c2
./a
./b
./c1
$ find -newerct @$(($(stat -c %Z c2)-1))
.
./c3
./d
./c2
./e
./c1
$ find -not -newerct @$(($(stat -c %Z c2)-1))
./a
./b

This should represent all possible sets of ctime relative to c2:

  1. ctime > c2
  2. ctimec2
  3. ctimec2
  4. ctime < c2

with somewhat fuzzy matching, at least.

The third command gets epoch ctime for the file c2, subtracts 1 via shell arithmetic and feeds this as reference to -newerct (the @ is needed for find to interpret is as such a timestamp) to find all files with ctime newer than this interpreted timestamp (see -newerXY in man find). The fourth command negates this match, and should in practice do what you want if I've understood the question correctly, if you put your reference file as c2 in my example.

Note that the "1 second" offset is somewhat arbitrary (which is what I meant by "fuzzy matching"), and one could imagine a situation where a bug could be constructed. However, timestamps of files are not "definite" anyway and can not be trusted to be, so I can't imagine it to generate either security or practical problems in real situations.

Actually, in practice you might even want to increase the 1 second offset (I see in your question that you use 1 minute right now), but that is an implementation detail.

share|improve this answer

Maybe pipe the find output into a loop of the test command which will let you use an "older-than" test:

find ... | while read file;
do
  [ "$file" -ot deployment_metadata.txt ] && echo "$file"
done
share|improve this answer
    
This works even in dash! –  Ярослав Рахматуллин Feb 22 at 22:10

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.