创建唯一文件名Windows批处理 [英] Create unique file name Windows batch

查看:134
本文介绍了创建唯一文件名Windows批处理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我看到有关创建从幼稚%TIME%唯一的文件名以合理的(但不足)%RANDOM%,许多职位。使用 WMIC操作系统获取localdatetime 是好多了,但它仍然可能失败在多个CPU /核的机器。在5+炮弹multple核心的机器上运行时,下面的脚本最终将失败。

I have seen many posts about creating a unique filename from the naive %TIME% to the plausible (but insufficient) %RANDOM%. Using wmic os get localdatetime is much better, but it can still fail on multiple CPU/core machines. The following script will eventually fail when run in 5+ shells on a multple core machine.

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION

FOR /L %%i IN (0, 1, 1000) DO (
    FOR /F "usebackq" %%x IN (`wmic os get localdatetime ^| find "."`) do (set MYDATE=%%x)
    ECHO MYDATE is now !MYDATE!
    IF EXIST testuniq_!MYDATE!.txt (
        ECHO FAILED ON !MYDATE!
        GOTO TheEnd
    )
    COPY NUL >testuniq_!MYDATE!.txt
)

:TheEnd
EXIT /B 0

有没有人有一个可靠的方式在shell脚本来创建一个唯一的文件名?

Does anyone have a reliable way to create a unique file name in a shell script?

推荐答案

这依赖于一个随机数理论上可以失败,即使是使用GUID的任何系统。但世界似乎已经接受了GUID是不够好。我见过code贴的地方,使用CSCRIPT JScript中生成一个GUID。

Any system that relies on a random number can theoretically fail, even one using a GUID. But the world seems to have accepted that GUIDs are good enough. I've seen code posted somewhere that uses CSCRIPT JScript to generate a GUID.

有其他的方法:

首先,我会假设你要创建一个唯一的临时文件。因为一旦你的过程结尾的文件将被删除,所有你必须​​做的是他的名字就是你的临时文件名的衍生物的资源建立一个排它锁。 (其实我去反向 - 临时名称是从锁定的资源名称派生的)。

First I will assume that you are trying to create a unique temporary file. Since the file will be deleted once your process ends, all you must do is establish an exclusive lock on a resource whose name is a derivative of your temp file name. (actually I go in reverse - the temp name is derived from the locked resource name).

重定向建立在输出文件的独占锁定,所以我只是得到一个名字从时间(与0.01秒preciscion),并试图锁定的文件在用户的Temp文件夹同名。如果失败比我环回,然后再试一次,直到成功。一旦我有成功,我保证能有锁的独家所有权,以及所有derivitives(除非有人故意破坏的系统)。

Redirection establishes an exclusive lock on the output file, so I simply derive a name from the time (with 0.01 second preciscion), and attempt to lock a file with that name in the user's temp folder. If that fails than I loop back and try again until I succeed. Once I have success, I am guaranteed to have sole ownership of that lock, and all derivitives (unless someone intentionally breaks the system).

在我的进程终止时,锁将被释放,并用相同名称的临时文件可在以后重复使用。但是脚本通常会删除终止时的临时文件。

Once my process terminates, the lock will be released, and a temp file with the same name could be reused later on. But the script normally deletes the temp file upon termination.

@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

由于循环到名称冲突应该是罕见的,除非你真的讲你的系统。如果是这样,你可以减少10倍的循环,如果你使用的几率 WMIC OS GET LOCALDATETIME 而不是%TIME%

如果你正在寻找一个永久唯一的名称,那么问题就比较难一点,因为你不能无限期地保持锁定。对于这种情况下,我建议WMIC OS LocalDateTime方法,再加上两次检查的名称冲突。

If you are looking for a persistent unique name, then the problem is a bit more difficult, since you cannot maintain the lock indefinitely. For this case I recommend the WMIC OS LocalDateTime approach, coupled with two checks for name collision.

第一次检查只是验证该文件不存在。但是,这是一个竞争条件 - 两个过程可以使在同一时间检查。第二检查创建该文件(空)并在其上建立一个临时独占锁。关键是要确保锁被保持一段时间长于它需要另一个进程来检查文件是否存在。我很懒,所以我简单地使用TIMEOUT建立1秒的等待 - 比路更应该是必要的。

The first check simply verifies the file does not already exist. But this is a race condition - two processes could make the check at the same time. The second check creates the file (empty) and establishes a temporary exclusive lock on it. The trick is to make sure that the lock is maintained for a period of time that is longer than it takes for another process to check if the file exists. I'm lazy, so I simply use TIMEOUT to establish a 1 second wait - way more than should be necessary.

的:getUniqueFile例程需要三个参数 - 碱名,扩展名,并且其中所述的结果是要被存储的变量名称。该基地名称可以包含驱动器和路径信息。任何路径信息必须有效,否则程序将进入一个无限循环。这个问题可能是固定的。

The :getUniqueFile routine expects three arguments - a base name, an extension, and the variable name where the result is to be stored. The base name can include drive and path information. Any path information must be valid, otherwise the routine will enter an infinite loop. That issue could 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 be guaranteed to return a new unique file name for the given path. There is a lot of room for optimization to establish some command to execute during the lock check that takes "long enough" but not "too long"

这篇关于创建唯一文件名Windows批处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆