我认为可以通过使用GUID作为目录名称来避免循环:
function New-TemporaryDirectory {
$parent = [System.IO.Path]::GetTempPath()
[string] $name = [System.Guid]::NewGuid()
New-Item -ItemType Directory -Path (Join-Path $parent $name)
}
这是我对此C#解决方案的移植:
function New-TemporaryDirectory {
$parent = [System.IO.Path]::GetTempPath()
$name = [System.IO.Path]::GetRandomFileName()
New-Item -ItemType Directory -Path (Join-Path $parent $name)
}
GetRandomFileName
返回一个已存在于临时文件夹中的名称的概率有多大?
XXXXXXXX.XXX
,其中X可以是小写字母或数字。GetRandomFileName
可能会导致冲突另一方面,NewGuid
可以有2^122种可能性,使得冲突几乎不可能发生。
我也喜欢一句话的表述方式,虽然我担心会被踩。我的请求只是希望你把我自己的模糊负面情绪用言语表达出来。
New-TemporaryFile | %{ rm $_; mkdir $_ }
根据你是哪种纯粹主义者,你可以执行%{ mkdir $_-d }
,留下占位符以避免冲突。
同时也可以采用Join-Path $env:TEMP $(New-Guid) | %{ mkdir $_ }
的方式。
New-TemporaryFile | % { Remove-Item $_; New-Item -ItemType Directory -Path $_ }
- NReilingh-d
是为了避免所谓的“碰撞”,导致文件和目录之间发生问题。 - nik.shornikov这是user4317867的答案的一个变体。我在用户的Windows“Temp”文件夹中创建了一个新目录,并将临时文件夹路径作为变量($tempFolderPath
)提供:
$tempFolderPath = Join-Path $Env:Temp $(New-Guid)
New-Item -Type Directory -Path $tempFolderPath | Out-Null
这里有相同的脚本,以一行代码的形式提供:
$tempFolderPath = Join-Path $Env:Temp $(New-Guid); New-Item -Type Directory -Path $tempFolderPath | Out-Null
这里是完全限定的临时文件夹路径 ($tempFolderPath
) 的样子:
C:\Users\MassDotNet\AppData\Local\Temp\2ae2dbc4-c709-475b-b762-72108b8ecb9f
如果您想要一个循环解决方案,保证既不会出现竞争又不会发生碰撞,那么这里就是:
function New-TemporaryDirectory {
$parent = [System.IO.Path]::GetTempPath()
do {
$name = [System.IO.Path]::GetRandomFileName()
$item = New-Item -Path $parent -Name $name -ItemType "directory" -ErrorAction SilentlyContinue
} while (-not $item)
return $item.FullName
}
根据迈克尔·克罗帕特的答案中的分析,大多数情况下,它只会通过一次循环。很少会通过两次。几乎不可能通过三次。
function New-TemporaryDirectory {
$path = Join-Path ([System.IO.Path]::GetTempPath()) ([System.IO.Path]::GetRandomFileName())
#if/while path already exists, generate a new path
while(Test-Path $path)) {
$path = Join-Path ([System.IO.Path]::GetTempPath()) ([System.IO.Path]::GetRandomFileName())
}
#create directory with generated path
New-Item -ItemType Directory -Path $path
}
.NET已经有了[System.IO.Path] :: GetTempFileName()很长一段时间了;您可以使用它来生成一个文件(并捕获名称),然后在删除文件后创建具有相同名称的文件夹。
$tempfile = [System.IO.Path]::GetTempFileName();
remove-item $tempfile;
new-item -type directory -path $tempfile;
$tempfilename
变量在哪里被使用了? - sodawillow如果可能的话,我喜欢使用一行代码。@alroc .NET 也有 [System.Guid]::NewGuid()
$temp = [System.Guid]::NewGuid();new-item -type directory -Path d:\$temp
Directory: D:\
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 1/2/2016 11:47 AM 9f4ef43a-a72a-4d54-9ba4-87a926906948
$temp = New-Item -Type Directory -Path $env:TEMP -Name ([System.Guid]::NewGuid())
来设置$temp。 - IsAGuest如果你想的话,你可以非常高级地调用Windows API函数GetTempPathA()
,像这样:
# DWORD GetTempPathA(
# DWORD nBufferLength,
# LPSTR lpBuffer
# );
$getTempPath = @"
using System;
using System.Runtime.InteropServices;
using System.Text;
public class getTempPath {
[DllImport("KERNEL32.DLL", EntryPoint = "GetTempPathA")]
public static extern uint GetTempPath(uint nBufferLength, [Out] StringBuilder lpBuffer);
}
"@
Add-Type $getTempPath
$str = [System.Text.StringBuilder]::new()
$MAX_PATH = 260
$catch_res = [getTempPath]::GetTempPath($MAX_PATH, $str)
Write-Host $str.ToString() #echos temp path to STDOUT
# ... continue your code here and create sub folders as you wish ...
Path.GetTempPath
内部执行完全相同的代码。 - Martin Prikryl扩展自Michael Kropat的回答:https://dev59.com/tlsW5IYBdhLWcg3w0Z4j#34559554
Function New-TemporaryDirectory {
$tempDirectoryBase = [System.IO.Path]::GetTempPath();
$newTempDirPath = [String]::Empty;
Do {
[string] $name = [System.Guid]::NewGuid();
$newTempDirPath = (Join-Path $tempDirectoryBase $name);
} While (Test-Path $newTempDirPath);
New-Item -ItemType Directory -Path $newTempDirPath;
Return $newTempDirPath;
}
这应该消除任何碰撞问题。
GetRandomFileName()
和New-Item
放在一个循环中,以便在名称冲突的情况下自动重试。 - Ansgar Wiechers-Force
来创建不存在的父目录,但我错了,所以我更新了答案。 - Michael Kropat$name = (New-Guid).ToString('n')
,这将创建一个类似于450d881de6054d5894c7f7378bbb9f51
的字符串。 - zett42