{"id":343,"date":"2021-04-21T13:51:22","date_gmt":"2021-04-21T20:51:22","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/powershell-community\/?p=343"},"modified":"2021-04-22T10:38:04","modified_gmt":"2021-04-22T17:38:04","slug":"borrowing-a-built-in-powershell-command-to-create-a-temporary-folder","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/powershell-community\/borrowing-a-built-in-powershell-command-to-create-a-temporary-folder\/","title":{"rendered":"Borrowing a built-in PowerShell command to create a temporary folder"},"content":{"rendered":"<p><strong>Q:<\/strong> Hey I have a question for you. It seems silly and I know I could probably put something together with Get-Random. But can you think of another way to create a temporary folder with a random name in PowerShell?<\/p>\n<p>Ideally, I&#8217;d like it to be in a user&#8217;s own &#8220;Temporary Folder&#8221; is possible.<\/p>\n<p><strong>A:<\/strong> We sure can! If Doctor Scripto was sitting here right now, I&#8217;d see that little green haired person shout out &#8220;Never fear, Scripto is here!&#8221;<\/p>\n<h2>New-TemporaryFile Cmdlet<\/h2>\n<p>Within PowerShell there is a built in Cmdlet called <code>New-TemporaryFile<\/code>. Running this cmdlet simply creates a random 0 byte file in the <code>$ENV:Temp folder<\/code> in whichever platform you are working in.<\/p>\n<p>However, we can <em>borrow<\/em> the filename created and use it to create a folder instead. It\u2019s not really difficult, but maybe just not thought of very often.<\/p>\n<p>When we execute the following cmdlet we get output similar to this as it generates a new 0 Byte random file in the User&#8217;s Temp folder stored in <code>$ENV:Temp<\/code><\/p>\n<pre><code class=\"language-output\">PS&gt; New-TemporaryFile\n\nMode                 LastWriteTime         Length Name\n----                 -------------         ------ ----\n-a----         3\/31\/2021   9:25 PM              0 tmpA927.tmp<\/code><\/pre>\n<p>Ok, that really wasn\u2019t that impressive but what if we were to do this instead?<\/p>\n<pre><code class=\"language-powershell\">$File = New-TemporaryFile<\/code><\/pre>\n<p>Now we\u2019ve created the file and stored it away in the <code>$File<\/code> object. With this we can remove the file of course using the <code>Remove-Item<\/code> cmdlet<\/p>\n<pre><code class=\"language-powershell\">Remove-Item -path $File -force<\/code><\/pre>\n<p>HA! I\u2019ve already saved some time! The <code>$File<\/code> object is still there with the information I want to use.<\/p>\n<p>So, I could access the name in the object property and use it to create a directory instead in the following manner.<\/p>\n<pre><code class=\"language-powershell\">New-Item -ItemType Directory -Path $File.Name<\/code><\/pre>\n<p>But the problem is that it would be in whatever default folder PowerShell was looking into at the time.<\/p>\n<p>Hmmmmm\u2026. How to solve that?<\/p>\n<p>But there is a built in variable called <code>$ENV:Temp<\/code> which targets the exact Temporary folder that the <code>New-TemporaryFile<\/code> cmdlet uses as well!<\/p>\n<p>I can then take that variable and the original name of the Temporary file and combine them together like this.<\/p>\n<pre><code class=\"language-powershell\">$ENV:Temp + '\\' + $File.Name<\/code><\/pre>\n<p><em>or<\/em><\/p>\n<p>I can even put them together in a single String like this.<\/p>\n<pre><code class=\"language-powershell\">\"$($ENV:Temp)\\$($File.Name)\"<\/code><\/pre>\n<p>With this I could just create a new temporary directory under our temp folder in this manner.<\/p>\n<pre><code class=\"language-powershell\">New-Item -ItemType Directory -Path \"$($ENV:Temp)\\$($File.Name)\"<\/code><\/pre>\n<p>Now to identify where the file ended up, I could same thing as last time by storing it as an object like <code>$DirectoryName<\/code> if I wanted. Then I could remove the &#8220;Random Directory name&#8221; later if I needed to.<\/p>\n<pre><code class=\"language-powershell\">$Folder=New-Item -ItemType Directory -Path \"$($ENV:Temp)\\$($File.Name)\"<\/code><\/pre>\n<p>Then when I am done with that folder that was presumably used to hold some garbage data. I can just use <code>Remove-Item<\/code> again.<\/p>\n<p>But because it&#8217;s a directory, I need to add <code>-recurse -force<\/code> to ensure all data and Subfolders are removed.<\/p>\n<pre><code class=\"language-powershell\">Remove-Item -Path $Folder -Recurse -Force<\/code><\/pre>\n<p>But here is the fun and neat bit. If you needed on a regular basis, we could make this into a quick function for your code, module or to impress friends with!<\/p>\n<pre><code class=\"language-powershell\">Function New-TemporaryFolder {\n    # Create Temporary File and store object in $T\n    $File = New-TemporaryFile\n\n    # Remove the temporary file .... Muah ha ha ha haaaaa!\n    Remove-Item $File -Force\n\n    # Make a new folder based upon the old name\n    New-Item -Itemtype Directory -Path \"$($ENV:Temp)\\$($File.Name)\" \n}<\/code><\/pre>\n<p>Now at this point I had thought my journey was complete. It was until I posted the solution to the <a href=\"https:\/\/www.facebook.com\/groups\/pscommunityblog\/\">Facebook group for the PowerShell Community Blog<\/a> to share.<\/p>\n<p>A fellow member of the Community noted the approach, while neat, was not very efficient.<\/p>\n<p>At that point I dug into the code on Github for the open source version of PowerShell 7.x to see how it was done there.<\/p>\n<p>In reading the source code for <code>New-TemporaryItem<\/code> I was able to see the .NET object being used to generate the file. It turns out there is also a .NET method that can be used to create just that temporary name which all I wanted to use in the first place for the directory name.<\/p>\n<p>When I ran this in the PowerShell Console it produced the following output of a New Temporary Folder<\/p>\n<pre><code class=\"language-output\">PS&gt; [System.IO.Path]::GetTempFileName()\nC:\\Users\\Administrator\\AppData\\Local\\Temp\\2\\tmp3864.tmp<\/code><\/pre>\n<p>This was exactly what I wanted, that random temporary Name to be consumed for the <code>New-Item<\/code> Cmdlet. With this approach the function became a lot simpler and far more efficient!<\/p>\n<pre><code class=\"language-powershell\">Function New-TemporaryFolder {\n    # Make a new folder based upon a TempFileName\n    New-Item -ItemType Directory -Path([System.IO.Path]::GetTempFileName())\n}<\/code><\/pre>\n<p>But alas my victory was short lived. This method still created the file, it didn&#8217;t just display the name. So the function ended up failing.<\/p>\n<p>But since really I just wanted that format to be used for the temporary directory. Plus the format for the temporary filename was as simple as <code>tmpxxxx.tmp<\/code> where the xxxx was a random hexadecimal number, I came up with a better idea!<\/p>\n<p>Just create a number between 0 and 65535 with <code>Get-Random<\/code> and use the <code>[convert]<\/code> accelerator to change it the 4 character Hexadecimal number instead.<\/p>\n<p>The end result looked like this and gave me the desired result I wanted.<\/p>\n<pre><code class=\"language-output\">PS&gt; \"$($Env:temp)\\tmp$([convert]::tostring((get-random 65535),16).padleft(4,'0')).tmp\"\nC:\\Users\\doctorscripto\\AppData\\Local\\Temp\\tmp5633.tmp\n<\/code><\/pre>\n<p>Now I ended up with a working function that could produce the desired output I wanted and in a more efficient manner.<\/p>\n<pre><code class=\"language-powershell\">Function New-TemporaryFolder {\n    # Make a new folder based upon a TempFileName\n    $T=\"$($Env:temp)\\tmp$([convert]::tostring((get-random 65535),16).padleft(4,'0')).tmp\"\n    New-Item -ItemType Directory -Path $T\n}<\/code><\/pre>\n<p>Why did all of this pop into my head? I was actually creating some PowerShell for customer and needed a consistent and random set of folders in a common and easily erasable location.<\/p>\n<p>I was hoping that we had a <code>New-TemporaryDirectory<\/code> cmdlet, but found it was just as easy to write one by <em>borrowing<\/em> an existing cmdlet.<\/p>\n<p>It was fun as well to discover how I could improve on the solution by reading the <a href=\"https:\/\/github.com\/PowerShell\/PowerShell\/blob\/master\/src\/Microsoft.PowerShell.Commands.Utility\/commands\/utility\/NewTemporaryFileCommand.cs\">Source code for New-TemporaryItem<\/a> on Github.<\/p>\n<p>Thanks to a little nudging from the Community. So a big Thank you to Joel Bennett for the critique! \ud83d\ude42<\/p>\n<p>Sean Kearney &#8211; Customer Engineer\/Microsoft &#8211; @PowerShellMan<\/p>\n<p><em>&#8220;Remember with great PowerShell comes great responsibilty&#8230;&#8221;<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Q: Hey I have a question for you. It seems silly and I know I could probably put something together with Get-Random. But can you think of another way to create a temporary folder with a random name in PowerShell? Ideally, I&#8217;d like it to be in a user&#8217;s own &#8220;Temporary Folder&#8221; is possible. A: [&hellip;]<\/p>\n","protected":false},"author":51959,"featured_media":77,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[13],"tags":[29,28,27,30],"class_list":["post-343","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-powershell","tag-existing-cmdlet","tag-fun-trick","tag-function","tag-new-purpose"],"acf":[],"blog_post_summary":"<p>Q: Hey I have a question for you. It seems silly and I know I could probably put something together with Get-Random. But can you think of another way to create a temporary folder with a random name in PowerShell? Ideally, I&#8217;d like it to be in a user&#8217;s own &#8220;Temporary Folder&#8221; is possible. A: [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/powershell-community\/wp-json\/wp\/v2\/posts\/343","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/powershell-community\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/powershell-community\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell-community\/wp-json\/wp\/v2\/users\/51959"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell-community\/wp-json\/wp\/v2\/comments?post=343"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/powershell-community\/wp-json\/wp\/v2\/posts\/343\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell-community\/wp-json\/wp\/v2\/media\/77"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/powershell-community\/wp-json\/wp\/v2\/media?parent=343"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell-community\/wp-json\/wp\/v2\/categories?post=343"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell-community\/wp-json\/wp\/v2\/tags?post=343"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}