Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PowerShell format text file

Tags:

powershell

I get the below output from a PowerShell query. I don't have access to the server to run the query, so I have no option to influence the output format.

Example:

Name          : folderC
FullName      : D:\folderA\folderB\folderC
Length        :
CreationTime  : 2/8/2014 11:12:58 AM
LastAccessTime: 2/8/2014 11:12:58 AM

Name          : filename.txt
FullName      : D:\folderA\folderB\filename.txt
Length        : 71560192
CreationTime  : 11/25/2015 3:10:43 PM
LastAccessTime: 11/25/2015 3:10:43 PM

How can I format above content to get something more usable, maybe like a table format like so:

Name|FullName|Length|CreationTime|LastAccessTime
like image 561
ratanmalko Avatar asked Jan 20 '16 12:01

ratanmalko


People also ask

Can PowerShell edit text files?

PowerShell can be used to perform different windows operations, such as creating folders, directories. Similarly, text files can also be handled using PowerShell; we can edit text files to append or remove the content from the text files.

How do you write to a text file in PowerShell?

To create a new text file and write to it, use the > redirection operator. If you use this operator to write PowerShell stream to a text file, it overwrites the content of the text file. However, if you wan to update a text file without overwriting its content, you use the >> redirection operator.


Video Answer


2 Answers

I think you need to split the text into records, replace the colons with equals so that you can use the ConvertFrom-StringData to turn each record into a hash which you can then feed into New-Object to convert into an object. Outputting the the object into pipe separated data can then be done with the ConvertTo-Csv. Something like so:

$x = @"
Name           : folderC
FullName       : D:\folderA\folderB\folderC
Length         : 0
CreationTime   : 2/8/2014 11:12:58 AM
LastAccessTime : 2/8/2014 11:12:58 AM

Name           : filename.txt
FullName       : D:\folderA\folderB\filename.txt
Length         : 71560192
CreationTime   : 11/25/2015 3:10:43 PM
LastAccessTime : 11/25/2015 3:10:43 PM
"@

($x -split '[\r\n]+(?=Name)') | % {
  $_ -replace '\s+:\s+', '='
} | % {
  $_ | ConvertFrom-StringData
} | % {
  New-Object psobject -Property $_
}  | ConvertTo-Csv -Delimiter '|' -NoTypeInformation
like image 78
Dave Sexton Avatar answered Oct 03 '22 01:10

Dave Sexton


As @alroc notes in a comment on the question, it is possible that objects are available to the OP, given that they state that the output is "from a Powershell query" - if so, simple reformatting of the object array using the usual cmdlets is an option.
By contrast, this answer assumes that only a text representation, as printed in the question, is available.

Dave Sexton's answer is a simpler and more elegant choice, if:

  • the input has no empty values (the OP's sample input does).
  • the input file is small enough to be read into memory as a whole.

Consider the approach below to avoid the issues above and/or if you want more control over how the input is converted into custom objects, notably with respect to creating properties with types other than [string]: extend the toObj() function below (as written, all properties are also just strings).


Get-Content File | % `
  -begin {
    function toObj([string[]] $lines) {
      $keysAndValues = $lines -split '(?<=^[^ :]+)\s*: '
      $htProps = @{}
      for ($i = 0; $i -lt $keysAndValues.Count; $i += 2) {
        $htProps.($keysAndValues[$i]) = $keysAndValues[$i+1]
      }
      return [PSCustomObject] $htProps
    }
    $lines = @()
  } `
  -process {
    if ($_.trim() -ne '') { 
      $lines += $_
    } else {
      if ($lines) { toObj $lines }
      $lines = @()
    }
  } `
  -end {
    if ($lines) { toObj $lines }
  } | Format-Table

Explanation:

  • Uses ForEach-Object (%) with separate begin, process, and end blocks.

  • The -begin, executed once at the beginning:

    • Defines helper function toObj() that converts a block of contiguous nonempty input lines to a single custom object.

      • toObj() splits an array of lines into an array of contiguous key-value elements, converts that array to a hashtable, which is then converted to a custom object.
    • Initializes array $lines, which will store the lines of a single block of contiguous nonempty input lines

  • The -process block, executed for each input line:

    • If the input line at hand is nonempty: Adds it to the current block of contiguous nonempty input lines stored in array $lines.

    • Otherwise: Submits the current block to toObj() for conversion to a custom object, and then resets the $lines array to start the next block. In effect, toObj() is invoked for each paragraph (run of nonempty lines).

  • The -end block, executed once at the end:

    • Submits the last paragraph to toObj() for conversion to a custom object.
  • Finally, the resulting array of custom objects is passed to Format-Table.

like image 41
mklement0 Avatar answered Oct 03 '22 00:10

mklement0