我正在尝试创建要在批处理文件中使用的临时文件的路径。
有环境变量%TEMP%
和%TMP%
来获取当前用户的临时目录。但是如何建立一个肯定还不存在的文件名呢?
当然我可以使用内置变量%RANDOM%
并创建类似bat~%RANDOM%.tmp
的内容,但此方法无法确保文件当前不存在(或者在我第一次在磁盘上创建并写入之前,它将由另一个应用程序巧妙地创建 - 尽管这一切都不太可能。
我知道我可以通过附加%DATE%
/ %TIME%
或仅添加多个%RANDOM%
实例来降低此类冲突的可能性,但这不是我想要的......
注意:根据this post,.NET中有一种方法(Path.GetTempFileName()
)完全符合我的要求(显然除了错误的编程语言)
答案 0 :(得分:7)
尝试下一个代码段:
@echo off
setlocal EnableExtensions
rem get unique file name
:uniqLoop
set "uniqueFileName=%tmp%\bat~%RANDOM%.tmp"
if exist "%uniqueFileName%" goto :uniqLoop
或创建程序
:uniqGet
:创建一个修复文件名模板的文件(在您的案例中为bat~%RANDOM%.tmp
); :uniqGetByMask
:创建一个可变文件名模板的文件。请注意过程调用中%random%
引用的四倍百分号:prefix%%%%random%%%%suffix.ext
。另请注意程序中call set "_uniqueFileName=%~2"
内的advanced usage: CALL
ing internal commands。代码可以如下:
@ECHO OFF
SETLOCAL enableextensions
call :uniqGet uniqueFile1 "%temp%"
call :uniqGet uniqueFile2 "%tmp%"
call :uniqGet uniqueFile3 d:\test\afolderpath\withoutspaces
call :uniqGet uniqueFile4 "d:\test\a folder path\with spaces"
call :uniqGetByMask uniqueFile7 d:\test\afolder\withoutspaces\prfx%%%%random%%%%sffx.ext
call :uniqGetByMask uniqueFile8 "d:\test\a folder\with spaces\prfx%%%%random%%%%sffx.ext"
set uniqueFile
pause
goto :continuescript
rem get unique file name procedure
rem usage: call :uniqGetByMask VariableName "folderpath\prefix%%%%random%%%%suffix.ext"
rem parameter #1=variable name where the filename save to
rem parameter #2=folder\file mask
:uniqGetByMask
rem in the next line (optional): create the "%~dp2" folder if does not exist
md "%~dp2" 2>NUL
call set "_uniqueFileName=%~2"
if exist "%_uniqueFileName%" goto :uniqGetByMask
set "%~1=%_uniqueFileName%"
rem want to create an empty file? remove the `@rem` word from next line
@rem type nul > "%_uniqueFileName%"
exit /B
goto :continuescript
@rem get unique file name procedure
@rem usage: call :uniqGet VariableName folder
@rem parameter #1=variable name where the filename save to
@rem parameter #2=folder where the file should be about
:uniqGet
@rem in the next line (optional): create the "%~2" folder if does not exist
md "%~2" 2>NUL
set "_uniqueFileName=%~2\bat~%RANDOM%.tmp"
if exist "%_uniqueFileName%" goto :uniqGet
set "%~1=%_uniqueFileName%"
@rem want to create empty file? remove the `@rem` word from next line
@rem type nul > "%_uniqueFileName%"
exit /B
:continueScript
<强>输出强>:
==>D:\bat\SO\32107998.bat
uniqueFile1=D:\tempUser\me\bat~21536.tmp
uniqueFile2=D:\tempUser\me\bat~15316.tmp
uniqueFile3=d:\test\afolderpath\withoutspaces\bat~12769.tmp
uniqueFile4=d:\test\a folder path\with spaces\bat~14000.tmp
uniqueFile7=d:\test\afolder\withoutspaces\prfx26641sffx.ext
uniqueFile8=d:\test\a folder\with spaces\prfx30321sffx.ext
Press any key to continue . . .
答案 1 :(得分:2)
我建议你使用两种方法之一。 &#34;技术方法&#34;是使用JScript的FileSystemObject.GetTempName方法。 JScript是一种编程语言,预装在XP上的所有Windows版本中,并通过&#34; Batch-JScript&#34;批量使用。混合脚本非常简单:
@if (@CodeSection == @Batch) @then
@echo off
setlocal
for /F "delims=" %%a in ('CScript //nologo //E:JScript "%~F0"') do set "tempName=%%a"
echo Temp name: "%tempName%"
goto :EOF
@end
// JScript section
var fso = new ActiveXObject("Scripting.FileSystemObject");
WScript.Stdout.WriteLine(fso.GetTempName());
但是,最简单的方法是将数字存储在数据文件中,并且每次需要新名称时,获取数字,递增数字并将其存储在同一文件中。这将适用于&#34;只是&#34; 2147483647次!
rem Get next number
set /P "nextNum=" < NextNumber.txt
set /A nextNum+=1
echo %nextNum% > NextNumber.txt
set "tempName=File%nextNum%.txt"
echo Temp name: %tempName%
答案 2 :(得分:1)
首先,使用单独的文件夹将大大降低其他程序入侵的可能性。因此,我们将临时文件存储在一个非常长且特定的私人文件夹中,以防止任何名称竞争。
生成名称时,您始终可以使用%random%
并尝试生成不存在的名称,但使用此操作的次数越多,其效果就越低。如果您计划使用此过程10次,因为随机函数限制为32000(大约),您的程序将花费永远产生随机尝试。
下一个最好的方法是在一个计数器上启动一个计数器并增加它,直到你有一个未使用的名字。这样你就可以保证你的程序最终会在合理的时间内找到一个名字,但是你的文件会堆积起来(这绝不是一个好的体验)
有些人做的事情(我建议你的情况)是将这些过程结合起来,在选择名字的同时有效减少脂肪,同时使用可靠的方法(两全其美):
@echo off
:: Set Temp Folder Path
set "tp=%temp%\Temporary Name Selection Test"
:: File name will be XXXXXX_YY.txt
:::: X's are randomly generated
:::: Y's are the incremented response to existing files
set x=%random%
set y=0
set "filename=Unexpected Error"
:loop
set /a y+=1
set "filename=%tp%\%x%_%y%.txt"
if exist %filename% goto loop
:: At this point, filename is all good
Echo %filename%
pause