Any system that relies on a random number can theoretically fail, even using a GUID. But the world seems to have agreed that the GUIDs are good enough. I saw somewhere code that uses CSCRIPT JScript to generate a GUID.
There are other ways:
At first, I assume that you are trying to create a unique temporary file. Since the file will be deleted after the process is complete, all you need to do is set an exclusive lock on the resource, whose name is derived from your temp file name. (in fact, I'm going the other way around - the name temp comes from the name of the locked resource).
Reassignment sets an exclusive lock on the output file, so I just get the name from time to time (with 0.01 second preciscion) and try to lock the file with this name in the temporary user folder. If this fails, I will go back and try again until I succeed. As soon as I succeed, I am guaranteed to get ownership of this castle and all derivatives (if someone does not intentionally violate the system).
Once my process is complete, the lock will be released, and a temporary file with the same name can be reused later. But the script usually deletes the temporary file after completion.
@echo off setlocal :getTemp set "lockFile=%temp%\%~nx0_%time::=.%.lock" set "tempFile=%lockFile%.temp" 9>&2 2>nul (2>&9 8>"%lockFile%" call :start %*) || goto :getTemp :: Cleanup 2>nul del "%lockFile%" "%tempFile%" exit /b :start :: Your code that needs the temp file goes here. This routine is called with the :: original parameters that were passed to the script. I'll simply write some :: data to the temp file and then TYPE the result. >"%tempFile%" echo The unique tempfile for this process is "%tempfile%" >>"%tempFile%" echo(%* type "%tempFile%" exit /b
A loop due to name clashes should be rare if you really don't stress your system. If so, you can reduce the chance of looping by 10 times by using WMIC OS GET LOCALDATETIME instead of %TIME% .
If you are looking for a permanent unique name, the problem is a bit more complicated, since you cannot maintain an indefinite lock. In this case, I recommend using the LocalDateTime method for the WMIC system in combination with two name conflict checking.
The first check simply verifies that the file does not exist yet. But this is a condition of the race - two processes can do the check at the same time. The second check creates a file (empty) and sets a temporary exclusive lock on it. The trick is to make sure that the lock is maintained for a certain period of time, which is longer than another process, to check if the file exists. I am lazy, so I just use TIMEOUT to set 1 second to wait - this is more than necessary.
Procedure: getUniqueFile expects three arguments - the base name, the extension, and the name of the variable in which the result should be stored. The base name may contain disk and path information. Any information about the path must be valid, otherwise the program will enter an infinite loop. This problem can be fixed.
@echo off setlocal :: Example usage call :getUniqueFile "d:\test\myFile" ".txt" myFile echo myFile="%myFile%" exit /b :getUniqueFile baseName extension rtnVar setlocal :getUniqueFileLoop for /f "skip=1" %%A in ('wmic os get localDateTime') do for %%B in (%%A) do set "rtn=%~1_%%B%~2" if exist "%rtn%" ( goto :getUniqueFileLoop ) else ( 2>nul >nul (9>"%rtn%" timeout /nobreak 1) || goto :getUniqueFileLoop ) endlocal & set "%~3=%rtn%" exit /b
The above should ensure that a new unique file name is returned for the given path. There are many possibilities for optimization to set some command to be executed during the lock check, which takes a lot of time but not too long.