Marcello has asked for the wisdom of the Perl Monks concerning the following question:

Hi, I'm looking for a way to create unique filenames based on a timestamp. Since multiple files can be created in a second, I need something that uses milliseconds or even microseconds. The module Time::HiRes could be used for this, but I am not able to install modules on this particular machine (Linux Redhat).

How can I create unique filenames based on timestamps without using modules?

TIA!

Replies are listed 'Best First'.
Re: Filenames based on timestamp
by janx (Monk) on Jun 27, 2002 at 12:53 UTC
    You might want to check perlfaq8 and read "How to measure time under one second".
    If you are lucky you can use that bit of information to get a more detailed timestamp.

    However, I would either try to get the sysadmin to install Time::HiRes or use perl-5.8.0RC2 (in a bit 5.8 ;-)), which has Time::HiRes as a core module.

    Otherwise I would suggest to read perlfaq5 "How do I make a temporary file name?".

    Kay

Re: Filenames based on timestamp
by robobunny (Friar) on Jun 27, 2002 at 12:50 UTC
    you could use the time that you've got available, then increment a counter at the end of the filename.
    my $time = time(); my $counter = 0; while(-e "$time_$counter") { $counter++; } open(F, ">$time_$counter") or die "blah blah $!";
    that way you get unique filenames that have a timestamp in them, they just have an extra number at the end.
      This is prone to race conditions when several processes are involved. Between the -e test and the actual file creation, a file of the name in question may have been created by another process.

      Makeshifts last the longest.

        that's true. you could work around that by also included a PID in the filename.
        while(-e "$time_$$_$counter") { $counter++; } open(F, ">$time_$$_$counter");
        of course, then the filenames won't necessarily be in ascending order chronologically.
Re: Filenames based on timestamp
by flounder99 (Friar) on Jun 27, 2002 at 13:26 UTC
    I think this will do what you want. It creates a nice human-readable filename. It assumes no one changes the system time. It also assumes that it will not get called more than 1000 times a second. If that is a problem change the three in the last "%03d" in the sprintf to a larger number.
    use strict; { my $lasttime; my $counter = 0; sub uniq_filename { my $time = time; if ($time == $lasttime) { $counter++; } else { $counter = 0; $lasttime = $time; } my @time = localtime($time); return sprintf ("%d%02d%02d%02d%02d%02d%03d", $time[5]+1900, $time[4]+1, $time[3], $time[2], $time[1], $time[0], $counter); } } for (1 .. 10) { print uniq_filename, "\n"; select undef, undef, undef, .25; } __OUTPUT__ 20020627092353000 20020627092354000 20020627092354001 20020627092354002 20020627092355000 20020627092355001 20020627092355002 20020627092355003 20020627092356000 20020627092356001

    --

    flounder

Re: Filenames based on timestamp
by George_Sherston (Vicar) on Jun 27, 2002 at 12:47 UTC
Re: Filenames based on timestamp
by krazken (Scribe) on Jun 27, 2002 at 13:36 UTC
    The easiest way that comes off the top of my head would be to gather the date/time information down to as far as you can, and then apply a tie breaker byte to the filename that you increment with each file you create. This way in the instance that you do create files within the given interval, you have the tiebreaker to ensure that the filename will be unique. Obviously the tiebreaker does not have to be 1 byte, but that is just how I have done it in the past. Hope this gives you a couple hints. thanks krazken
Re: Filenames based on timestamp
by atcroft (Abbot) on Jun 27, 2002 at 13:08 UTC

    Assuming this is not time-critical on the file creation (which I don't know to be a valid assumption, from the way you talk), the best idea I can see is something like this- get the timestamp, check for a file by that name, and if there is one that exists, increment some form of counter to be added to the name until no such filename exists. A possible code snippet might look like (forgive the rough code, but this was as I was thinking out the issue, and has not been tested):

    # filename format: filename-timestamp-counter.txt # assumption: $ts contains timestamp in unix time format # (seconds since epoch) # assumption: $filename created earlier with 'my', # and will contain the filename at end my @fnp = ('file', $ts, 0); $fnp[2]++ while (-e join('-', @fnp)); $filename = join('-', @fnp) . '.txt';

    YMMV. I am sure others may have additional suggestions, and I look forward to hearing them as well.