Behind the PowerShell Pipeline logo

Behind the PowerShell Pipeline

Subscribe
Archives
July 18, 2025

I Stream of PowerShell

Before I dive into today's content, I want to spend a moment to talk about this newsletter. First, although I refer to this as a newsletter, it is a newsletter in format only. I use a mailing service to deliver it to you and provide archive access. I typically think of a newsletter as a collection of related items of interest. The wrap-up I send out at the end of each month is a newsletter in that sense. I approach the other "issues" as a series of articles. I think of them as short book chapters.

Even though I write about topics like creating HTML reports, I'm not necessarily writing about the best way to accomplish that task. My goal with this newsletter is to teach you about PowerShell. I want to show you how to use PowerShell to solve problems, but I also want to show you how to think about using PowerShell. I want you to learn how to approach problems and how to use PowerShell to solve them. This means focusing on language, concepts, syntax, and techniques rather than specific solutions. Take my recent series of articles on creating HTML reports. I wasn't trying to show the best or only way to create HTML reports. Some of you may have no need to crete such reports. You should view all of my content as learning opportunities. You may not need to use here strings, import file content, or create files to build an HTML report. But those concepts could be useful in other contexts. When you read my content, I want you to think about how you can apply the content to your own work. What gaps in your knowledge are getting filled in? What new ideas are you getting about how to use PowerShell?

Focus on the journey I lead you through in each issue, not the destination or end product.

Today's topic, which I'm sure will encompass multiple issues, is a great example. I expect many of you aren't looking for where I end up, but there is value in exploring the process.

Alternate Data Streams

In Windows, we typically think of files and their content. We open a file, read its content, modify it, and save it. The content is saved with the file. However, there is much more to files in Windows than content alone.

Alternate data streams (ADS) are a feature of the NTFS file system that allows you to store additional metadata or content within a file without affecting the primary data stream. This means you can have multiple streams of data associated with a single file, each identified by a unique name. PowerShell provides cmdlets and parameters to work with these streams, allowing you to create, read, and manage them. I'm sure I've mentioned alternate data streams in the past.

In PowerShell, we can use commands with the -Stream parameter to work with these alternate data streams.

Get-Command -ParameterName Stream | Select Name

Name
----
Add-Content
Clear-Content
Get-Content
Get-Item
Out-String
Remove-Item
Set-Content

However you should still read help for these commands as -Stream can have other meanings.

Finding Streams

First, let's look at how to find streams associated with a file. Here's how we typically work with a file in PowerShell:

PS C:\temp> Get-tIem .\walrus.txt

    Directory: C:\temp

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---           7/10/2025  9:58 AM             29 walrus.txt

PS C:\temp> Get-Item .\walrus.txt | Get-Content
I am the PowerShell walrus!

When you read the help for Get-Item, you will see that it has a -Stream parameter. This parameter allows you to specify a stream to retrieve. You can use a wildcard character to retrieve all streams associated with the file.

PS C:\temp> Get-Item .\walrus.txt -Stream *

PSPath        : Microsoft.PowerShell.Core\FileSystem::C:\temp\walrus.txt::$DATA
PSParentPath  : Microsoft.PowerShell.Core\FileSystem::C:\temp
PSChildName   : walrus.txt::$DATA
PSDrive       : C
PSProvider    : Microsoft.PowerShell.Core\FileSystem
PSIsContainer : False
FileName      : C:\temp\walrus.txt
Stream        : :$DATA
Length        : 29

The stream name is :$DATA, which is the default data stream for files in Windows.

PS C:\temp> Get-Item .\n.txt -Stream :`$DATA

PSPath        : Microsoft.PowerShell.Core\FileSystem::C:\temp\n.txt::$DATA
PSParentPath  : Microsoft.PowerShell.Core\FileSystem::C:\temp
PSChildName   : n.txt::$DATA
PSDrive       : C
PSProvider    : Microsoft.PowerShell.Core\FileSystem
PSIsContainer : False
FileName      : C:\temp\n.txt
Stream        : :$DATA
Length        : 449

Note that this specific stream name begins with a colon (:) and is followed by $DATA. Because $DATA looks like a PowerShell variable, I am using the backtick to escape the $ so PowerShell treats it as a literal character.

Want to read the full issue?
GitHub Bluesky LinkedIn About Jeff
Powered by Buttondown, the easiest way to start and grow your newsletter.