Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/batch-file/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
创建唯一的文件名Windows批处理_Windows_Batch File_Cmd - Fatal编程技术网

创建唯一的文件名Windows批处理

创建唯一的文件名Windows批处理,windows,batch-file,cmd,Windows,Batch File,Cmd,我看过很多关于创建唯一文件名的帖子,从幼稚的%TIME%到看似合理(但不够)的%RANDOM%。使用wmic os get localdatetime要好得多,但在多个CPU/核心机器上仍然可能失败。当在多核机器上以5+个shell运行时,以下脚本最终将失败 @ECHO OFF SETLOCAL ENABLEDELAYEDEXPANSION FOR /L %%i IN (0, 1, 1000) DO ( FOR /F "usebackq" %%x IN (`wmic os get lo

我看过很多关于创建唯一文件名的帖子,从幼稚的%TIME%到看似合理(但不够)的%RANDOM%。使用wmic os get localdatetime要好得多,但在多个CPU/核心机器上仍然可能失败。当在多核机器上以5+个shell运行时,以下脚本最终将失败

@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脚本中创建唯一的文件名吗?

您可以使用
certutil
使用
%date%%time%%
种子对
%random%%进行base64编码,如下所示:

@echo off
setlocal

:: generate unique ID string
>"%temp%\~%~n0.%username%.a" echo %username%%date%%time%%random%
>NUL certutil -encode "%temp%\~%~n0.%username%.a" "%temp%\~%~n0.%username%.b"
for /f "usebackq EOL=- delims==" %%I in ("%temp%\~%~n0.%username%.b") do set "unique_id=%%I"
del "%temp%\~%~n0.%username%.a" "%temp%\~%~n0.%username%.b"

echo %unique_id%
如果多个用户从同一目录运行同一脚本,我将
%username%
添加到临时文件中以避免进一步冲突。我想您可以将
%random%
替换为
%username%
,以获得相同的效果。如果一个用户同时执行同一个代码块两次,那么只会出现冲突


(编辑:添加了
%username%
作为唯一性种子。)

使文件内容成为对象,使用指针memaddress作为文件名的第一部分,使用Rand()作为第二部分。即使运行多个实例,所有对象的内存地址都是唯一的。

@echo off
::在%1中生成临时文件名(默认临时文件)
:循环
设置/a y$$=%random%+100000
设置y$$=临时%y$$:~1,2%。%y$$:~-3%
如果存在“%temp%\%y$$$%”转到循环
设置“y$$=%temp%\%y$$%”并复制nul“%temp%\%y$$$%”>nul 2>nul
::y$$现在具有完整的临时文件名
如果“%1==”(设置“tempfile=%y$$%”)其他(设置“%1=%y$$%”)
这里是我的tempfile生成器的精简版本,用于在
%temp%
目录中创建名为
tempnn.nnn
的文件


一旦创建了
tempnn.nnn
,就可以通过在
%y$$%
中添加后缀来为流程创建尽可能多的临时文件,例如
%y$$%.a
等。当然,这假定其他进程在不使用此过程的情况下不会随机创建文件名。

下面的批处理JScript混合脚本使用WSH的fso.GetTempName()方法,该方法正是为此目的而设计的:

@if (@CodeSection == @Batch) @then

@echo off

for /F "delims=" %%a in ('cscript //nologo //E:JScript "%~F0"') do set "fileName=%%a"
echo Created file: "%fileName%"
goto :EOF

@end

var fso = new ActiveXObject("Scripting.FileSystemObject"), fileName;
do { fileName = fso.GetTempName(); } while ( fso.FileExists(fileName) );
fso.CreateTextFile(fileName).Close();
WScript.Echo(fileName);

任何依赖随机数的系统理论上都可能失败,即使是使用GUID的系统。但世界似乎已经接受guid已经足够好了。我在某处看到过使用CSCRIPT JScript生成GUID的代码

还有其他方法:

首先,我假设您正在尝试创建一个唯一的临时文件。由于该文件将在进程结束后被删除,因此您所要做的就是在其名称是临时文件名派生项的资源上建立独占锁。(事实上,我倒过来说-临时名称是从锁定的资源名称派生的)

重定向在输出文件上建立独占锁定,因此我只需从时间中派生一个名称(精度为0.01秒),并尝试在用户的临时文件夹中锁定具有该名称的文件。如果失败了,我将返回并重试,直到成功。一旦我成功了,我保证拥有锁和所有衍生产品的唯一所有权(除非有人故意破坏系统)

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

@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
由于名称冲突而导致的循环应该很少发生,除非您真的对系统造成压力。如果是这样,如果使用
WMIC OS GET LOCALDATETIME
而不是
%TIME%
,则可以将循环的机会减少10倍


如果您正在寻找一个持久的唯一名称,那么问题就有点困难,因为您不能无限期地维护锁。对于这种情况,我建议使用WMIC OS LocalDateTime方法,并对名称冲突进行两次检查

第一次检查只是验证该文件不存在。但这是一种竞争条件——两个进程可以同时进行检查。第二个检查创建文件(空)并在其上建立临时独占锁。诀窍是确保锁的维护时间比另一个进程检查文件是否存在所需的时间长。我很懒,所以我只是使用超时来建立一个1秒的等待方式,超出了需要的时间

:getUniqueFile例程需要三个参数—一个基名称、一个扩展名和存储结果的变量名。基本名称可以包括驱动器和路径信息。任何路径信息都必须有效,否则例程将进入无限循环。这个问题可以解决

@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

应保证上述内容为给定路径返回一个新的唯一文件名。在锁检查过程中,有很大的优化空间来建立一些要执行的命令,这些命令需要“足够长”而不是“太长”

我喜欢Aacini的JScript混合解决方案。只要我们借鉴了其他运行时环境,那么将.NET与PowerShell结合使用如何

@echo off
setlocal

for /f "delims=" %%I in ('powershell -command "[string][guid]::NewGuid()"') do (
    set "unique_id=%%I"
)

echo %unique_id%

很久以前,在一个名为alt.msdos.batch的galax..新闻组中,一名撰稿人坚持为每个问题发布QBASIC解决方案,并将其包装在一个批处理外壳中,声称这是批处理,因为它只使用微软提供的标准软件

很长一段时间后,他的错误行为被治愈了,但从那以后,我对混合方法严重过敏。当然,如果它能解决问题,诸如此类,而且有时无法逃避这个过程(例如,以静默方式运行批处理)。除此之外,我真的不想为学习一两门新语言而烦恼……因此,这就是为什么我回避*脚本解决方案。YMMV

所以-这里有另一种方法

@ECHO关闭
SETLOCAL
:rndtitle
设置“progtitle=我的批处理文件x%random%x”
标题“%progtitle%”
设置“下划线=”
设置“targetline=”
对于/f“delims=“%%a IN('TASKLIST/v^ | findstr/i/L/c:==”/c:“%progtitle%”)DO(
如果定义下划线(
如果定义为targetli
C:>title my shell a80en333xyb

C:>type getppid.ps1
(Get-WmiObject -Class Win32_Process -Filter "processid='$pid'").ParentProcessId

C:>powershell getppid.ps1
2380
powershell -NoProfile -Command "(Get-WmiObject -Class Win32_Process -Filter "processid=`'$pid`'").ParentProcessId"
C:>tasklist /v | find "2380"
cmd.exe                       2380 RDP-Tcp#0                  7      8,124 K Running         PHSNT\pwatson                                           0:00:03 my shell a80en333xyb
for /f "tokens=* delims={}" %%# in ('guid.bat') do set "unique=%%#"
echo %unique%
for /f "tokens=* delims={}" %# in ('guid.bat') do @set "unique=%#"
Add-Type -MemberDefinition @"
  // HWND WINAPI GetConsoleWindow(void)
  [DllImport("kernel32.dll", EntryPoint = "GetConsoleWindow")]
  public static extern IntPtr GetConsoleWindow();

  // DWORD GetWindowThreadProcessId(HWND hWnd, LPDWORD lpdwProcessId)
  [DllImport("user32.dll", EntryPoint = "GetWindowThreadProcessId")]
  public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);

  public static uint GetPID()
  {
    IntPtr h = GetConsoleWindow();
    if ((uint)h==0) return 0;
    uint rc = 0;
    GetWindowThreadProcessId(h, out rc);
    return rc;
  }
"@ -Name Win32 -NameSpace System

[System.Win32]::GetPID();
set MyPID=
for /f %%a in ('powershell -NoLogo -NoProfile -NonInteractive -EncodedCommand QQBkAGQALQBUAHkAcABlACAALQBNAGUAbQBiAGUAcgBEAGUAZgBpAG4AaQB0AGkAbwBuACAAQAAiAA0ACgBbAEQAbABsAEkAbQBwAG8AcgB0ACgAIgBrAGUAcgBuAGUAbAAzADIALgBkAGwAbAAiACwAIABFAG4AdAByAHkAUABvAGkAbgB0ACAAPQAgACIARwBlAHQAQwBvAG4AcwBvAGwAZQBXAGkAbgBkAG8AdwAiACkAXQANAAoAcAB1AGIAbABpAGMAIABzAHQAYQB0AGkAYwAgAGUAeAB0AGUAcgBuACAASQBuAHQAUAB0AHIAIABHAGUAdABDAG8AbgBzAG8AbABlAFcAaQBuAGQAbwB3ACgAKQA7AA0ACgBbAEQAbABsAEkAbQBwAG8AcgB0ACgAIgB1AHMAZQByADMAMgAuAGQAbABsACIALAAgAEUAbgB0AHIAeQBQAG8AaQBuAHQAIAA9ACAAIgBHAGUAdABXAGkAbgBkAG8AdwBUAGgAcgBlAGEAZABQAHIAbwBjAGUAcwBzAEkAZAAiACkAXQANAAoAcAB1AGIAbABpAGMAIABzAHQAYQB0AGkAYwAgAGUAeAB0AGUAcgBuACAAdQBpAG4AdAAgAEcAZQB0AFcAaQBuAGQAbwB3AFQAaAByAGUAYQBkAFAAcgBvAGMAZQBzAHMASQBkACgASQBuAHQAUAB0AHIAIABoAFcAbgBkACwAIABvAHUAdAAgAHUAaQBuAHQAIABsAHAAZAB3AFAAcgBvAGMAZQBzAHMASQBkACkAOwANAAoAcAB1AGIAbABpAGMAIABzAHQAYQB0AGkAYwAgAHUAaQBuAHQAIABHAGUAdABQAEkARAAoACkADQAKAHsADQAKACAASQBuAHQAUAB0AHIAIABoACAAPQAgAEcAZQB0AEMAbwBuAHMAbwBsAGUAVwBpAG4AZABvAHcAKAApADsADQAKACAAaQBmACAAKAAoAHUAaQBuAHQAKQBoAD0APQAwACkAIAByAGUAdAB1AHIAbgAgADAAOwANAAoAIAB1AGkAbgB0ACAAcgBjACAAPQAgADAAOwANAAoAIABHAGUAdABXAGkAbgBkAG8AdwBUAGgAcgBlAGEAZABQAHIAbwBjAGUAcwBzAEkAZAAoAGgALAAgAG8AdQB0ACAAcgBjACkAOwANAAoAIAByAGUAdAB1AHIAbgAgAHIAYwA7AA0ACgB9AA0ACgAiAEAAIAAtAE4AYQBtAGUAIABXAGkAbgAzADIAIAAtAE4AYQBtAGUAUwBwAGEAYwBlACAAUwB5AHMAdABlAG0ADQAKAFsAUwB5AHMAdABlAG0ALgBXAGkAbgAzADIAXQA6ADoARwBlAHQAUABJAEQAKAApADsADQAKAA^=^= 2^>nul') do (
  set "MyPID=%%~a"
)

if defined MyPID echo %MyPID%