How to Remove an Alternate Data Stream from a File in Batch Script
Alternate Data Streams (ADS) are hidden data storage units attached to standard files on the NTFS file system. While often used for legitimate purposes like tagging files from the internet (the "Zone.Identifier" stream), ADS can also be used to hide malicious code or junk data that bloats your drive.
If you have discovered a suspicious or unnecessary alternate stream, such as the "Blocked" tag on a downloaded script, you can use Batch scripting to remove it.
In this guide, we will look at how to strip specific streams and how to "unblock" files by deleting their zone identification.
The Challenge: No Native "Delete Stream" Command
Windows does not have a dedicated Batch command like delstream for removing alternate data streams. However, PowerShell, which is included with all modern versions of Windows, provides cmdlets that can cleanly remove streams. Calling these cmdlets from a Batch script is the standard and most reliable approach.
Method 1: Unblocking a Single File (Zone.Identifier)
The most common reason to remove an ADS is to "Unblock" a script or executable downloaded from the web. Windows stores a stream called :Zone.Identifier on downloaded files, which triggers the "This file came from another computer" security warning.
The Unblock-File cmdlet completely removes this stream:
@echo off
setlocal
set "targetFile=C:\Downloads\Install.exe"
echo Unblocking file: %targetFile%
powershell -Command "Unblock-File -Path '%targetFile%'"
if %ERRORLEVEL% EQU 0 (
echo [SUCCESS] The 'from internet' flag has been removed.
) else (
echo [ERROR] Could not unblock the file. Check the path or run as Administrator.
)
endlocal
pause
Method 2: Removing a Specific Named Stream
To remove a stream other than Zone.Identifier, use the Remove-Item cmdlet with the -Stream parameter. This completely deletes both the stream header and its data.
The Removal Script
@echo off
setlocal
:: Define the file and the stream you want to delete
set "file=C:\Reports\Report.pdf"
set "stream=SecretNote"
echo Removing stream '%stream%' from '%file%'...
:: Check if the stream exists before trying to delete
dir /R "%file%" 2>nul | findstr /C:"%stream%" >nul
if %ERRORLEVEL% NEQ 0 (
echo [SKIP] Stream not found.
endlocal
pause
exit /b
)
:: Completely remove the stream header and data
powershell -Command "Remove-Item -Path '%file%' -Stream '%stream%'"
if %ERRORLEVEL% EQU 0 (
echo [SUCCESS] Stream deleted.
) else (
echo [ERROR] Could not remove stream. Access denied or file in use.
)
endlocal
pause
Method 3: Removing All Alternate Streams from a File
If a file has multiple alternate data streams and you want to strip them all at once, you can use PowerShell to enumerate every stream, filter out the primary data stream, and remove the rest.
The Strip-All Script
@echo off
setlocal
set "file=C:\Data\SensitiveData.zip"
echo Removing all alternate data streams from %file%...
:: Get-Item -Stream * lists all streams on the file
:: We filter out :$DATA (the primary content stream) to avoid destroying the file
:: Each remaining alternate stream is then removed individually
powershell -Command "Get-Item -Path '%file%' -Stream * | Where-Object { $_.Stream -ne ':$DATA' } | ForEach-Object { Remove-Item -Path '%file%' -Stream $_.Stream }"
if %ERRORLEVEL% EQU 0 (
echo [SUCCESS] All alternate data streams have been removed.
) else (
echo [ERROR] Could not remove streams. Check the path or run as Administrator.
)
endlocal
pause
This removes every alternate stream, including legitimate metadata that Windows or applications may have attached. Only use this on data files you control. Do not run this on system files or application binaries, as they may rely on specific streams to function correctly.
Method 4: Unblocking All Files in a Directory
If you want to unblock every file in a directory at once (e.g., after downloading a repository of scripts), use a recursive Unblock-File command:
@echo off
setlocal
set "targetDir=C:\Downloads\ScriptRepo"
echo Unblocking all files in %targetDir%...
:: Use PowerShell's Unblock-File for a safe, recursive cleanup
powershell -Command "Get-ChildItem -Path '%targetDir%' -Recurse | Unblock-File"
echo All files are now marked as safe and local.
endlocal
pause
Summary
Removing an alternate data stream in Batch is a task that relies on calling PowerShell cmdlets from your script.
- To unblock a single file: Use
Unblock-File. - To delete a specific named stream: Use
Remove-Itemwith the-Streamparameter. - To strip all streams from a file: Use
Get-Item -Stream *to enumerate andRemove-Item -Streamto delete each one. - To unblock a whole folder: Use a recursive
Get-ChildItem | Unblock-Filepipeline.
By mastering these techniques, you can ensure your files are clean, localized, and free of hidden data or metadata that could interfere with your scripts or compromise your security.