0

I have a requirement to identify sequence gap in a set of files. Sequence starts at FILENAME_0001 and ends at FILENAME_9999. After this the sequence is restarted from 0001.

To implement a proper sequence check I used ls -rt to pick the files in order of modified time and the compared with the previous files sequence number. If the previous file was 9999 I check whether the next one is 0001 (to accommodate the sequence reset).

Recently I came across a scenario where files were listed in the below order:

FILENAME_0001 
FILENAME_0002
FILENAME_0005
FILENAME_0003
FILENAME_0004
FILENAME_0006
FILENAME_0007

This was because files 3, 4 & 5 had the same modified time to the second. Only the millisecond was different. So I am guessing ls -rt considers only upto the seconds. Could someone suggest a workaround?

3
  • If I understand correctly, you're creating the files ordered by the sequence no (which is also increasing time), but not all files are created - so there are missing values in the sequence, which you're trying to identify. If so, cant you just sort the files by their seq nos and look for the missing ones ? Commented Feb 11, 2016 at 10:08
  • Yes. But note that seq numbers reset at 9999. So the way you suggested it will fail when I have files FILENAME_9999, FILENAME_0001, FILENAME_0002 Commented Feb 11, 2016 at 10:19
  • What Unix variant are you running this on? Getting at sub-second timestamps isn't portable. Commented Feb 11, 2016 at 22:24

2 Answers 2

1

If your find has printf, print out the mtime in seconds followed by the filename, then use sort, and finally cut:

find . -type f -printf "%T@\t%f\n" |
sort -k 1n -k 2 |
cut -f 2-

The find outputs TIMESTAMP FILENAME on each line. The sort first sorts the timestamps in numerical order. If the timestamps are equal, it will use the filename as a last resort. The cut removes the timestamp from the output.

EDIT: Your perl solution works, but I would do it differently. Here's the simplest:

find . -type f -print | 
perl -lne 'print (((stat($_))[9]."\t".$_)' |
sort -k 1n -k 2 |
cut -f 2-

No need to convert the time to a string and back again. Just output stat's mtime as a numeric value as find would have done.

4
  • Sounds good. I'll test it tomorrow and let you know. I don't have access to the system now. Commented Feb 11, 2016 at 12:11
  • This work in my home. But the actual box where I needed it to run doesn't support it 😔. The version of find I have installed doesn't up port printf Commented Feb 12, 2016 at 2:59
  • What kind of system is it? (uname -a should be a clue.) Does it support the stat command with format control? (stat -c ) Can you install GNU find? Commented Feb 12, 2016 at 7:00
  • I use HP-UX system. However I am marking your answer also as correct since if worked on my home machine. Commented Feb 12, 2016 at 7:07
1

Finally got it working. I used the below code:

for FILENAME in $(ls...); do
FILE_TIME=$(perl -e '@d=localtime ((stat(shift))[9]); printf "%4d%02d%02d%02d%02d%02d\n", $d[5]+1900,$d[4]+1,$d[3],$d[2],$d[1],$d[0]' $FILENAME)
echo "$FILE_TIME $FILENAME"
done | sort -k 1n -k 2 | cut -d" " -f2

I use HP-UX system.

1
  • This works, but for a slightly less cumbersome way, check out my edit to my answer :) Commented Feb 12, 2016 at 11:13

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.