Create a temporary directory in PowerShell?

三世轮回 提交于 2019-12-09 07:41:08

问题


PowerShell 5 introduces the New-TemporaryFile cmdlet, which is handy. How can I do the same thing but instead of a file create a directory? Is there a New-TemporaryDirectory cmdlet?


回答1:


I think it can be done without looping by using a GUID for the directory name:

function New-TemporaryDirectory {
    $parent = [System.IO.Path]::GetTempPath()
    [string] $name = [System.Guid]::NewGuid()
    New-Item -ItemType Directory -Path (Join-Path $parent $name)
}

Original Attempt With GetRandomFileName

Here's my port of this C# solution:

function New-TemporaryDirectory {
    $parent = [System.IO.Path]::GetTempPath()
    $name = [System.IO.Path]::GetRandomFileName()
    New-Item -ItemType Directory -Path (Join-Path $parent $name)
}

Analysis Of Possibility Of Collision

How likely is it that GetRandomFileName will return a name that already exists in the temp folder?

  • Filenames are returned in the form XXXXXXXX.XXX where X can be either a lowercase letter or digit.
  • That gives us 36^11 combinations, which in bits is around 2^56
  • Invoking the birthday paradox, we'd expect a collision once we got to around 2^28 items in the folder, which is about 360 million
  • NTFS supports about 2^32 items in a folder, so it is possible to get a collision using GetRandomFileName

NewGuid on the other hand can be one of 2^122 possibilities, making collisions all but impossible.




回答2:


I also love one-liners, and I'm begging for a downvote here. All I ask is that you put my own vague negative feelings about this into words.

New-TemporaryFile | %{ rm $_; mkdir $_ }

Depending on the type of purist you are, you can do %{ mkdir $_-d }, leaving placeholder to avoid collisions.

And it's reasonable to stand on Join-Path $env:TEMP $(New-Guid) | %{ mkdir $_ } also.




回答3:


Here's my attempt:

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
}



回答4:


If you want the looping solution that is guaranteed to be both race- and collision-free, then here it is:

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
}

According to the analysis in Michael Kropat's answer, the vast majority of the time, this will pass only once through the loop. Rarely will it pass twice. Virtually never will it pass three times.




回答5:


.NET has had [System.IO.Path]::GetTempFileName() for quite a while; you can use this to generate a file (and the capture the name), then create a folder with the same name after deleting the file.

$tempfile = [System.IO.Path]::GetTempFileName();
remove-item $tempfile;
new-item -type directory -path $tempfile;



回答6:


I love one liners if possible. @alroc .NET also has [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  



回答7:


Expanding from Michael Kropat's answer: https://stackoverflow.com/a/34559554/8083582

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;
}

This should eliminate any issues with collisions.



来源:https://stackoverflow.com/questions/34559553/create-a-temporary-directory-in-powershell

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!