{"id":384,"date":"2021-05-24T10:26:24","date_gmt":"2021-05-24T17:26:24","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/powershell-community\/?p=384"},"modified":"2021-05-24T10:27:40","modified_gmt":"2021-05-24T17:27:40","slug":"how-to-send-output-to-a-file","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/powershell-community\/how-to-send-output-to-a-file\/","title":{"rendered":"How to send output to a file"},"content":{"rendered":"<p><strong>Q:<\/strong> Is there an easy way to save my script output to a text file rather than displaying it on screen?<\/p>\n<p><strong>A:<\/strong> Of course &#8211; there are multiple ways to do just that!<\/p>\n<h2>PowerShell and Output<\/h2>\n<p>One of PowerShell&#8217;s great features is the way it automatically formats output. You type a command &#8211; PowerShell gives you the output it thinks you want. If the default output is not what you need, use the formatting cmdlets like <code>Format-Table<\/code> and <code>Format-List<\/code> to get what you want. But sometimes, what you want is getting output to a file, not to the console. You might want to run a command or script that outputs information to a file and sends this file via email or possibly FTP. Or, you might want to view it in a text editor or print it out later.<\/p>\n<p>Once you have created the code (script, fragment, or a single command) that creates the output you need, you can use several techniques to send that output to a file.<\/p>\n<h2>The alternative methods<\/h2>\n<p>There are (at least) four ways to get output to a file. You can use any or all of:<\/p>\n<ul>\n<li><code>*-Content<\/code> cmdlets<\/li>\n<li><code>Out-File<\/code> cmdlet<\/li>\n<li>Redirection operators<\/li>\n<li>.NET classes<\/li>\n<\/ul>\n<p>Writing this reminds me of my friends in Portugal who tell me there are 1000 ways to cook bacalao (cod). Then they whisper: plus the way my mother taught me. If there are more techniques for file output, I expect to see them in the comments to this article. \ud83d\ude03<\/p>\n<h2>Using the <code>*-Content<\/code> cmdlets<\/h2>\n<p>There are four <code>*-Content<\/code> cmdlets:<\/p>\n<ul>\n<li><code>Add-Content<\/code> &#8211; appends content to a file.<\/li>\n<li><code>Clear-Content<\/code> &#8211; removes all content of a file.<\/li>\n<li><code>Get-Content<\/code> &#8211; retrieves the content of a file.<\/li>\n<li><code>Set-Content<\/code> &#8211; writes new content which replaces the content in a file.<\/li>\n<\/ul>\n<p>The two cmdlets you use to send command or script output to a file are <code>Set-Content<\/code> and <code>Add-Content<\/code>. Both cmdlets convert the objects you pass in the pipeline to strings, and then output these strings to the specified file. A very important point here &#8211; if you pass either cmdlet a non-string object, these cmdlets use each object&#8217;s <strong>ToString()<\/strong> method to convert the object to a string before outputting it to the file. For example:<\/p>\n<pre><code class=\"language-powershell-console\">PS&gt; Get-Process -Name pwsh | Set-Content -Path C:\\Foo\\AAA.txt\nPS&gt; Get-Content -Path C:\\Foo\\AAA.txt\nSystem.Diagnostics.Process (pwsh)\nSystem.Diagnostics.Process (pwsh)\nSystem.Diagnostics.Process (pwsh)\nSystem.Diagnostics.Process (pwsh)\nSystem.Diagnostics.Process (pwsh)<\/code><\/pre>\n<p>In many cases, this conversion does not produce what you expect (or want). In this example, PowerShell found the 5 pwsh.exe processes, converted each to a string using <strong>ToString()<\/strong>, and outputs those strings to the file. When you use <strong>ToString<\/strong> .Net&#8217;s default implementation prints out the object&#8217;s type name, like this:<\/p>\n<pre><code class=\"language-powershell-console\">PS&gt; $Foo = [System.Object]::new()\nPS&gt; $Foo.ToString()\nSystem.Object<\/code><\/pre>\n<p>The <strong>System.Diagnostics.Process<\/strong> class&#8217;s implementation of the <strong>ToString()<\/strong> method is only marginally richer. The <strong>ToString()<\/strong> method for this class outputs the object&#8217;s type name and includes the process name as you see above. But it is far short of the richer output you see when you use <code>Get-Process<\/code> from the console.<\/p>\n<p>The <code>*-Content<\/code> cmdlets are useful when you are building up a report programmatically. For example, you could create a string, then add to it repeatedly in a script, finally outputting the report string to a file. You can see the basic approach to building up a report in <a href=\"https:\/\/github.com\/doctordns\/Wiley20\/blob\/master\/10%20-%20Reporting\/10.8%20-%20Creating%20a%20Hyper-V%20Status%20Report.ps1\">this script that creates a Hyper-V VM summary report<\/a>.<\/p>\n<p>You can improve the output from <code>Set-Content<\/code> by using <code>Out-String<\/code>, like this:<\/p>\n<pre><code class=\"language-powershell-console\">PS&gt; # Get Powershell processes, convert to string, then output to a file\nPS&gt; Get-Process -Name pwsh |\n      Out-String |\n        Set-Content .\\Process.txt\nPS&gt; # View the file\nPS&gt; Get-Content .\\Process.txt\n\n NPM(K)    PM(M)      WS(M)     CPU(s)      Id  SI ProcessName\n ------    -----      -----     ------      --  -- -----------\n     70    56.65     109.05      13.19    2876   1 pwsh\n     87   100.72     161.84       4.69   31252   1 pwsh\n     63    54.40      93.90      22.27   31500   1 pwsh\n    145   295.50     355.05     465.28   38132   1 pwsh\n     64    52.82      95.29      52.95   38436   1 pwsh<\/code><\/pre>\n<p>Now that is looking a lot more like what I suspect you wanted! But there is an easier way.<\/p>\n<h2>Using <code>Out-File<\/code><\/h2>\n<p>The <code>Out-File<\/code> cmdlet sends output to a file. The cmdlet, however, uses PowerShell&#8217;s formatting system to write to the file rather than using <strong>ToString()<\/strong>. Using this cmdlet means Powershell sends the file the same display representation that you see from the console.<\/p>\n<p>Using <code>Out-File<\/code> looks like this:<\/p>\n<pre><code class=\"language-powershell-console\">PS&gt; # Get Powershell processes and output to a file\nPS&gt; Get-Process -Name pwsh | Out-File -Path C:\\Foo\\pwsh.txt\nPS&gt; Get-Content -Path C:\\Foo\\pwsh.txt\n\n NPM(K)    PM(M)      WS(M)     CPU(s)      Id  SI ProcessName\n ------    -----      -----     ------      --  -- -----------\n     72    57.62     109.93      13.41    2876   1 pwsh\n     92   136.95     202.20       5.44   31252   1 pwsh\n     63    54.40      93.90      22.30   31500   1 pwsh\n    145   295.49     355.05     465.80   38132   1 pwsh\n     64    52.88      95.32      52.98   38436   1 pwsh\n<\/code><\/pre>\n<p>The <code>Out-File<\/code> cmdlet gives you control over the output that PowerShell composes and sends to the file. You can use the <code>-Encoding<\/code> parameter to tell PowerShell how to encode the output. By default, PowerShell 7 uses the <a href=\"https:\/\/en.wikipedia.org\/wiki\/UTF-8\">UTF-8<\/a> encoding, but you can choose others should you need to.<\/p>\n<p>If you output very wide tables, you can use the <code>-Width<\/code> parameter to adjust the output&#8217;s width. In PowerShell 7, you can specify a value of up to 1024, enabling very wide tables. Although the documentation does not specify any maximum upper value, formatting is erratic if you specify a width greater than 1025 characters.<\/p>\n<h2>The Redirection Operators<\/h2>\n<p>There are two PowerShell operators you can use to redirect output: <code>&gt;<\/code> and <code>&gt;&gt;<\/code>. The <code>&gt;<\/code> operator is equivalent to <code>Out-File<\/code> while <code>&gt;&gt;<\/code> is equivalent to <code>Out-File -Append<\/code>. The redirection operators have other uses like redirecting error or verbose output streams. You can read more about the <a href=\"https:\/\/docs.microsoft.com\/powershell\/module\/microsoft.powershell.core\/about\/about_redirection\">redirection operator(s) in the online help<\/a>.<\/p>\n<h2>Using .NET Classes<\/h2>\n<p>There are several .NET classes you can leverage to produce output to a file. C# developers have to use these classes since C# does not have PowerShell&#8217;s formatting engine. There are three classes, depending on your use case, that you might use:<\/p>\n<ul>\n<li><a href=\"https:\/\/docs.microsoft.com\/dotnet\/api\/system.io.binarywriter\">BinaryWriter<\/a> &#8211; Writes primitive types in binary to a stream.<\/li>\n<li><a href=\"https:\/\/docs.microsoft.com\/dotnet\/api\/system.io.streamwriter\">StreamWriter<\/a> &#8211; writes characters to a stream in a particular encoding.<\/li>\n<li><a href=\"https:\/\/docs.microsoft.com\/dotnet\/api\/system.io.stringwriter\">StringWriter<\/a> &#8211; writes information to a string. With this class, Powershell stores the string information in a <a href=\"https:\/\/docs.microsoft.com\/dotnet\/api\/system.text.stringbuilder\">StringBuilder<\/a> object.<\/li>\n<\/ul>\n<p>Of these three, the class you are most likely to use to send output to a file is the <strong>StreamWriter<\/strong> class. Like this:<\/p>\n<pre><code class=\"language-powershell\"># Get the directories in C:\\\n$Dirs = Get-ChildItem -Path C:\\ -Directory\n# Open a stream writer\n$File   = 'C:\\Foo\\Dirs.txt'\n$Stream = [System.IO.StreamWriter]::new($File)\n# Write the folder names for these folders to the file\nforeach($Dir in $Dirs) {\n  $Stream.WriteLine($Dir.FullName)\n}\n# Close the stream\n$Stream.Close()<\/code><\/pre>\n<p>You can use <code>Get-Content<\/code> to view the generated content, like this:<\/p>\n<pre><code class=\"language-powershell-console\">PS&gt; Get-Content -Path c:\\Foo\\Dirs.txt\nC:\\AUDIT\nC:\\Boot\nC:\\Foo\nC:\\inetpub\nC:\\jea\nC:\\NVIDIA\nC:\\PerfLogs\nC:\\Program Files\nC:\\Program Files (x86)\nC:\\PSDailyBuild\nC:\\ReskitApp\nC:\\Temp\nC:\\Users\nC:\\WINDOWS<\/code><\/pre>\n<p>For most PowerShell-using IT Pros, using the classes in the <code>System.IO<\/code> namespace is useful in two situations. The first case is where you are doing a quick and dirty translation of a complex C# fragment to PowerShell. The stream writer example above is based on the C# sample in the <a href=\"https:\/\/docs.microsoft.com\/dotnet\/api\/system.io.streamwriter\">SteamWriter&#8217;s documentation page<\/a>. In some cases, it might be easier to translate the code to PowerShell than to recode it to use cmdlets. The second use case is where you are writing very large amounts of data to the file. There is a limit on how big a .NET string object can be, restricting your report-writing. If you are writing reports of tens of millions of lines of output (e.g. in an IoT scenario), writing one line at a time may be a way to avoid out of memory issues. I doubt many IT Pros encounter such issues, but it&#8217;s always a good idea to know there are alternatives where you need them.<\/p>\n<h2>Summary<\/h2>\n<p>You have many options over how you send output to a file. Each method has different use cases, as I mentioned above. In most cases, I prefer using <code>Out-File<\/code>. Using <code>Set-Content<\/code> is useful to set the initial contents of a file, for example, if you create a new script file based on a standard corporate template. From the console, doing stuff quick\/dirty, using the redirection operators can be useful alternatives. Using the <code>System.IO<\/code> classes is another way to perform output and useful for very large output sets. So lots of options &#8211; and I would not be surprised to find more methods I&#8217;d not considered!<\/p>\n<h2>Tip of the Hat<\/h2>\n<p>I based this article on one written for the earlier Scripting Guys blog <a href=\"https:\/\/devblogs.microsoft.com\/scripting\/how-can-i-save-output-to-a-text-file\/\">How Can I Save Output to a Text File?<\/a>. I am not sure who the author was.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Q: Is there an easy way to save my script output to a text file rather than displaying it on screen? A: Of course &#8211; there are multiple ways to do just that! PowerShell and Output One of PowerShell&#8217;s great features is the way it automatically formats output. You type a command &#8211; PowerShell gives [&hellip;]<\/p>\n","protected":false},"author":4034,"featured_media":77,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[13],"tags":[36,3],"class_list":["post-384","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-powershell","tag-output","tag-powershell"],"acf":[],"blog_post_summary":"<p>Q: Is there an easy way to save my script output to a text file rather than displaying it on screen? A: Of course &#8211; there are multiple ways to do just that! PowerShell and Output One of PowerShell&#8217;s great features is the way it automatically formats output. You type a command &#8211; PowerShell gives [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/powershell-community\/wp-json\/wp\/v2\/posts\/384","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\/4034"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell-community\/wp-json\/wp\/v2\/comments?post=384"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/powershell-community\/wp-json\/wp\/v2\/posts\/384\/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=384"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell-community\/wp-json\/wp\/v2\/categories?post=384"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell-community\/wp-json\/wp\/v2\/tags?post=384"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}