I had a need to create a set of directories - one per day. Normally I would use the date in ISO format: YYYY-MM-DD since it naturally sorts in date order. However for this particular application, I wanted reverse order - most recent date at the top, older and progressively less interesting dates following.

This routine generates a directory name based on a unix timestamp value (default 'today'), that includes a sort code prefix to force reverse date ordering:

sub day_dir { my($day, $month, $year) = (localtime(shift || time))[3,4,5]; my @sym = ('1'..'6', 'A'..'Z'); my $code = $sym[(138 - $year) & 31] . $sym[(11 - $month) & 15] . $sym[(31 - $day) & 31]; return sprintf('%s-%04u-%02u-%02u', $code, $year + 1900, $month + +1, $day); }

Sample output:

WFY-2010-01-01
X11-2009-12-31
X2Y-2009-11-01
X3C-2009-10-23

You could adapt it to put the day of the week ('Mon', 'Tue', 'Wed' ...) or indeed anything you like, after the sort code.

Replies are listed 'Best First'.
Re: Reverse Date Sorted Directory Names
by jwkrahn (Abbot) on Oct 23, 2009 at 03:13 UTC

    Operating systems do not sort file names in a directory.    It is only the application you are using to display the file names that is sorting them so determine what option your particular application uses to reverse the sort order and use that.

      I think you'll find that by default most graphical and command line file management tools will sort directory contents alphabetically. So I'm using this technique to ensure that one particular directory is sorted in the most useful order by default. This technique does nothing that would stop people using different sorting options if they so desired - it just means that they probably won't need to.

Re: Reverse Date Sorted Directory Names
by roho (Bishop) on Oct 28, 2009 at 19:56 UTC
    I'm trying to understand your use of the @sym array. Why do you build the array using "1-6" instead of all the digits "1-9", or "0-9" like you use all the letters of the alphabet "A-Z"?

    "Its not how hard you work, its how much you get done."

      Why do you build the array using "1-6" instead of all the digits "1-9", or "0-9" like you use all the letters of the alphabet "A-Z"

      There's really nothing significant about my choice of characters. I needed a set of 32* unique characters that could be guaranteed to sort consistently. There are 26 letters of the alphabet so I needed six more. I couldn't use both uppercase and lowercase letters because file managers will often sort case insensitively. There are a limited number of punctuation characters that are safe to use in filenames so I just went for the digits 1-6.

      I could have used 0-9 and A-V, but I preferred to use fewer digits and more letters to reduce the chance of a numeric code being taken as part of the date.

      Alternatively, since there are 14 bits of significant data in the code, I could have spread it out over 4 characters rather than three. Then I'd only have needed 16 unique symbols (e.g.: A-P) to represent the 4 bit payload for each character:

      sub day_dir { my($day, $month, $year) = (localtime(shift || time))[3,4,5]; my $code = sprintf('%04X', (((138 - $year) & 31) << 9) + (((11 - $month) & 15) << 5) + ((31 - $day) & 31) ); $code =~ tr/0-9A-F/A-P/; return sprintf('%s-%04u-%02u-%02u', $code, $year + 1900, $month + +1, $day); }

      * Eagle eyed readers will note that I really only needed 31 unique symbols but I was being conservative.

Re: Reverse Date Sorted Directory Names
by Anonymous Monk on Nov 08, 2009 at 05:36 UTC
    Your approach is cool, but you can also use # of days remaining till some epoch seconds . You can do whatever to that number and make that prefix. That would make the code easier.