web-dev-qa-db-ja.com

PowerShellで一時ディレクトリを作成しますか?

PowerShell 5ではNew-TemporaryFile cmdlet 、これは便利です。ファイルの代わりにディレクトリを作成して同じことを行うにはどうすればよいですか?ありますか New-TemporaryDirectoryコマンドレット?

25
Michael Kropat

ディレクトリ名にGUIDを使用することで、ループなしで実行できると思います。

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

GetRandomFileNameを使用した元の試み

このC#ソリューション の私のポートはここにあります:

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

衝突の可能性の分析

GetRandomFileNameがtempフォルダーに既に存在する名前を返す可能性はどのくらいですか?

  • ファイル名はXXXXXXXX.XXXの形式で返されます。Xは小文字または数字です。
  • これにより、36 ^ 11の組み合わせが得られます。これはビット単位で約2 ^ 56です
  • birthday paradox を呼び出すと、フォルダー内の約2 ^ 28個のアイテム(約3億6,000万個)に到達すると、衝突が予想されます。
  • NTFSはフォルダ内の約2 ^ 32アイテムをサポートしています なので、GetRandomFileNameを使用して衝突を取得することが可能です

一方でNewGuid2 ^ 122の可能性の1つ 。衝突はほとんど不可能です。

40
Michael Kropat

ワンライナーも大好きです。ここで下票をお願いします。私が尋ねるのは、あなたがこれについて私自身の漠然とした否定的な感情を言葉に入れてくれるということだけです。

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

純粋主義者のタイプに応じて、衝突を避けるためにプレースホルダーを残して_%{ mkdir $_-d }_を実行できます。

また、Join-Path $env:TEMP $(New-Guid) | %{ mkdir $_ }の上に立つことも合理的です。

16
nik.shornikov

これが私の試みです:

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
}
3
sodawillow

.NETにはかなり以前から[System.IO.Path]::GetTempFileName()がありました。これを使用してファイルを生成(および名前をキャプチャ)し、ファイルを削除した後に同じ名前のフォルダーを作成できます。

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

可能であれば、ライナーが1つ大好きです。 @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  
2
user4317867

レースとコリジョンの両方がないことが保証されているループソリューションが必要な場合は、次のとおりです。

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
}

Michael Kropat's answer の分析によると、ほとんどの場合、これはループを1回だけ通過します。まれに2回通過します。事実上、3回通過することはありません。

2
John Freeman