5

My end goal here is to cd to a directory in powershell and then list all the alternate data stream files, then output all their content to a CSV.

I currently have the first two parts scripted:

cd c:\users\profilename\downloads\
gci -recurse | % { gi $_.FullName -stream * } | where stream -ne ':$Data'

To open an example data stream file, open cmd, cd to a directory, then run:

dir /r

After this, grab the zone identified name of one of the files and run this command without the :$data.

Example before removing :$Data

notepad test.docx:Zone.Identifier:$Data

After removing(run this command):

notepad test.docx:Zone.Identifier

How would I go about taking the output of the second command and using the PSPath field to open each of these files and then output all the contents in to one CSV file?

Any help is greatly appreciated.

mklement0
  • 382,024
  • 64
  • 607
  • 775
user3290171
  • 121
  • 1
  • 3
  • 19

3 Answers3

3

Presuming your are after the Stream content:

## Q:\Test\2018\11\19\SO_53380498.ps1
Pushd $ENV:USERPROFILE\Downloads
Get-ChildItem -Recurse | ForEach-Object {
  Get-Item $_.FullName -Stream *
} | Where-Object Stream -ne ':$Data' | 
      Select-Object FileName,Stream,
        @{n='CreationTime';e={(Get-Item $_.FileName).CreationTime}},
        @{n='LastWriteTime';e={(Get-Item $_.FileName).LastWriteTime}},
        @{n='Content';e={gc "$($_.FileName):$($_.Stream)"}} |
          Export-Csv Streams.csv -NoTypeInformation

Shorted output of the generated Streams.csv file
(date format depends on locale/user settings):

> gc .\Streams.csv
"FileName","Stream","CreationTime","LastWriteTime","Content"
"C:\Users\LotPings\Downloads\2018-06-27-raspbian-stretch.zip","Zone.Identifier","2018-07-29 22:13:03","2018-07-29 22:16:41","[ZoneTransfer] ZoneId=3"

If your final destination for the csv supports multiline fields, you could do -join "`n" on the content.

0

I think this might be close to what you want:

$files = gci -recurse | % { gi $_.FullName -stream * } | where stream -ne ':$Data' | select filename,stream,@{'name'='identifier';"e"={"$($_.filename)$($_.stream)"}}

Broken into multi-lines for legibility:

$files = Get-ChildItem -Recurse | 
    Where-Object { Get-Item $_.FullName -Stream * } | 
    Where-Object {$_.Stream -ne ':$Data'} | 
    Select-Object -Properties filename, stream, @{'name'='identifier';"e"={"$($_.filename)$($_.stream)"}}
JohnLBevan
  • 22,735
  • 13
  • 96
  • 178
Thom Schumacher
  • 1,469
  • 13
  • 24
  • To get this to print in the terminal really quickly (for example to see if Zone.Identifier was set for files, causing all kinds of issues) use: `$files = gci -recurse | % { gi $_.FullName -stream * } | where stream -ne ':$Data' | select filename,stream,@{'name'='identifier';"e"={"$($_.filename)$($_.stream)"}}; write-output $files` – sommmen Nov 17 '20 at 11:08
0

As ADS may contain binary data, I would not dump it into a text file, especially not into a formatted text file like CSV. To view the content of ADS, you can display a hexdump of its content, e. g.:

Get-ChildItem -Recurse | Get-Item -Stream * | ? {$_.Stream -ne ':$DATA'} | % {
  Write-Host "`n`n$($_.FileName):$($_.Stream)" -NoNewline
  Get-Content -LiteralPath $_.FileName -Stream $_.Stream -Raw | Format-Hex
}

This solution will also work for UNC paths, like paths to a network share.

stackprotector
  • 10,498
  • 4
  • 35
  • 64