PowerShell 5 представляет New-TemporaryFile
командлет, что очень удобно. Как я могу сделать то же самое, но вместо файла создать каталог? Есть ли командлет New-TemporaryDirectory
?
Создать временный каталог в PowerShell?
Ответы (9)
Я думаю, что это можно сделать без зацикливания, используя 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
вернет имя, которое уже существует во временной папке?
- Имена файлов возвращаются в форме
XXXXXXXX.XXX
, где X может быть строчной буквой или цифрой. - Это дает нам 36 ^ 11 комбинаций, что в битах составляет около 2 ^ 56.
- Вызывая парадокс дня рождения, мы ожидаем столкновения, как только мы дойдем до 2 ^ 28 элементов в папка, а это около 360 миллионов
- NTFS поддерживает около 2 ^ 32 элементов в папке, поэтому можно получить коллизию, используя
GetRandomFileName
NewGuid
с другой стороны, может быть одной из 2 ^ 122 возможностей, что делает столкновения почти невозможны.
GetRandomFileName()
и New-Item
в цикл, чтобы автоматически повторить попытку в случае конфликта имен.
- person Ansgar Wiechers; 02.01.2016
-Force
для создания несуществующих родительских каталогов, но я ошибался и обновил ответ.
- person Michael Kropat; 02.01.2016
Мне также нравятся однострочные сообщения, и я прошу проголосовать против. Все, о чем я прошу, это выразить словами мои смутные негативные чувства по этому поводу.
New-TemporaryFile | %{ rm $_; mkdir $_ }
В зависимости от того, какой вы пурист, вы можете сделать %{ mkdir $_-d }
, оставив заполнитель, чтобы избежать коллизий.
И на Join-Path $env:TEMP $(New-Guid) | %{ mkdir $_ }
тоже стоит стоять.
New-TemporaryFile | % { Remove-Item $_; New-Item -ItemType Directory -Path $_ }
- person NReilingh; 02.03.2019
-d
не позволяет избежать коллизий. (Что, если вы используете один и тот же подход в двух разных сценариях одновременно?) Но тогда вы не пытались избежать столкновений, не так ли? ;-)
- person jpaugh; 02.10.2019
-d
предназначен для предотвращения так называемого «столкновения» между результирующим файлом и каталогом.
- person nik.shornikov; 04.10.2019
New-TemporaryFile | %{ rm $_; mkdir "${_}d" }
.
- person Dave F; 08.03.2021
Вот вариант ответа пользователя4317867. Я создаю новый каталог в пользовательской папке 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
}
while
и New-Item
команды.
- person ComFreek; 04.04.2018
У .NET уже довольно давно есть [System.IO.Path]::GetTempFileName()
; вы можете использовать это для создания файла (и сохранения имени), а затем создать папку с тем же именем после удаления файла.
$tempfile = [System.IO.Path]::GetTempFileName();
remove-item $tempfile;
new-item -type directory -path $tempfile;
$tempfilename
используется?
- person sodawillow; 02.01.2016
Я люблю одинарные вкладыши, если это возможно. @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
если хотите, можете проявить крайность и вызвать функцию 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
делает для вас внутри компании.
- person Martin Prikryl; 26.03.2021
Расширение из ответа Майкла Кропата: 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;
}
Это должно устранить любые проблемы с коллизиями.
while
и New-Item
команды, точно так же, как другой ответ выше.
- person ComFreek; 04.04.2018