le has asked for the wisdom of the Perl Monks concerning the following question:
Hi folks,
I'm looking for a module or some other algorithm, that can
generate unique filenames (and maybe returns the filehandle).
I'm currently working on a web app, that writes a file
into a directory.
The problem is, that the filenames should be unique, so if
the script attempts to create two files at the same time the
files don't clobber.
I hope you get what I mean, something like "I need a new file,
and I think the filename 99887766 is ok, but if there's already
99887766, give me 99887767."
Re: "unique" filename?
by quidity (Pilgrim) on Dec 03, 2000 at 22:22 UTC
|
use File::MkTemp;
$dir = '.'; # directory to create file in
$string = mktemp('tempXXXXXX',$dir);
open(F,$string);
Will return a unique file name, you can also have it return a unique file handle so that there is no chance of opening an identical file in two instances of your script:
use File::MkTemp;
$dir = '.'; # directory to create file in
$fh = mkstemp('tempXXXXXX',$dir);
print $fh "stuff";
$fh->close;
You can add more 'X's, but you need at least six. | [reply] [d/l] [select] |
Re: "unique" filename?
by Fastolfe (Vicar) on Dec 03, 2000 at 22:17 UTC
|
For generating, say, unique temporary files, use IO::File::new_tmpfile. In addition there's the POSIX::tmpnam() function which would get you a unique filename (subject to a race condition, however, since there's a period between when it's generated and when it's used).
In a pinch, use something like this:
$num = 12345;
$dir = "/some/dir/";
$num++ while -e "$dir/$num";
open(F, ">$dir/$num") or die ...
But of course, there's still a race condition. A more secure solution would be to take advantage of sysopen and O_EXCL to iterate through filenames:
use Fcntl;
use FileHandle;
$num++ while !sysopen(F, "$dir/$num", O_EXCL|O_CREAT, 0777) && $! eq "
+File exists";
die "$dir/$num: $!" if $!;
Once you start adding all of the bells and whistles, though, you're just re-implementing IO::File new_tmpfile. | [reply] [d/l] [select] |
Re: "unique" filename?
by 2501 (Pilgrim) on Dec 04, 2000 at 01:05 UTC
|
$filename = $$.time;
This is a combination of process ID and time. This would prevent duplicate file names from being a possibility.
| [reply] [d/l] |
|
Actually, that wouldn't prevent duplicate filenames at all, depending on how fast you're generating filenames. For example, look what the following does:
while (1) {
print $$.time."\n";
}
Also, on Win32, there's a non-zero chance of a PID being reused.
| [reply] [d/l] |
|
When you log into a site, you have two options.
You can start running a script from a new connection or you can use an existing connection.
Since only one person can be using a PID at a time, the combination of time and PID is fine.
| [reply] |
|
|
|
Re: "unique" filename?
by the_slycer (Chaplain) on Dec 04, 2000 at 21:01 UTC
|
I use the following, which seems to work well (though results in some horribly long file names).
my $outfile = localtime;
print "$outfile\n";
$outfile=~s/\s|://g;
$outfile="$outfile" . rand($outfile);
$outfile=~s/\.//g; #for win32 - doesn't like multiple dots
print $outfile;
| [reply] [d/l] |
Re: "unique" filename?
by tune (Curate) on Dec 04, 2000 at 05:18 UTC
|
nobody answered the original question. (that is what i learned from revote hearings CNN Live...:)))
do {
$newfilename = $$.time();
} until (!-e $newfilename);
print $newfilename;
# and then do your stuff
--
tune | [reply] [d/l] |
|
| [reply] |
|
but the existing file can be removed by another thread in less time than 1 second. I understand why I have got downvoted, but the point is not on the method of creating the unique filename it is on how to avoid overwrinting the existing file.
--
tune
| [reply] |
|
|
|