Я знаю, что параметр -streams позволяет вам многое делать с альтернативными потоками данных, прикрепленными к файлам, но он не работает с папками и томами.
2 ответа
Вроде работает. Здесь я добавляю объявление в «d:\», а затем удаляю его.
> Set-Content -Path d:\ -Value "Hello, World" -Stream Fred
> Get-Content -Path d:\ -Stream Fred
Hello, World
> Remove-Item -Path d:\ -Stream Fred
Confirm
The item at D:\ has children and the Recurse parameter was not specified. If you continue, all children will be removed with the item. Are you sure you want to continue?
[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"): y
E:\scratch\st> Get-Content -Path d:\ -Stream Fred
Get-Content : Could not open the alternate data stream 'Fred' of the file 'D:\'.
Предупреждение кажется неверным. В моем тестировании не было удалено ни одного ребенка, когда я указал "Y".
Осторожно: когда вы экспериментируете, убедитесь, что вы указали параметр -Stream
в Remove-Item
иначе вы можете удалить все на томе.
PS D:\PShell> Get-Command -All -ParameterName 'stream' | Format-Table -AutoSize -Wrap
CommandType Name ModuleName
----------- ---- ----------
Cmdlet Add-Content Microsoft.PowerShell.Management
Cmdlet Clear-Content Microsoft.PowerShell.Management
Cmdlet Get-Content Microsoft.PowerShell.Management
Cmdlet Get-Item Microsoft.PowerShell.Management
Cmdlet Out-String Microsoft.PowerShell.Utility
Cmdlet Remove-Item Microsoft.PowerShell.Management
Cmdlet Set-Content Microsoft.PowerShell.Management
Все вышеперечисленные командлеты должны хорошо работать с альтернативными потоками данных, связанными с файлом, папкой или диском, если вы знаете имя потока. К сожалению, командлет Get-ChildItem
отсутствует в списке, поскольку он не допускает параметр -Stream
. С другой стороны, можно перечислить альтернативные потоки данных файла, используя Get-Item
для FileSystem, который говорит о параметре -Stream
:
Получает указанный альтернативный поток файлов NTFS из файла. Введите имя потока. Подстановочные знаки поддерживаются. Чтобы получить все потоки, используйте звездочку (
*
). Этот параметр недопустим для папок.
Без использования внешней утилиты, такой как streams.exe
из Sysinternals, вы можете перечислить все альтернативные потоки данных в командной строке с помощью команды dir /R
(Vista и выше) (и проанализировать вывод из . cmd /D /C dir /R
в PowerShell),
К сожалению, dir /R
не работает вместе с ключом /B
Более того,
dir /R /A:-D
возвращает все потоки (обычные файлы данных и имена ADS) для файлов,dir /R /A:D
возвращает все потоки (имена папок и ADS) для папок, кроме корневой папки / диска,dir /R
возвращает все имена (обычные и ADS) для файлов и папок, кроме корневой папки / диска.
Я написал два .BAT
которые анализируют dir /R
и могут форматировать вывод как CSV
:
ADSdisk.bat [/CSVformat]
возвращает имена ADS для всех активных (локальных) дисков иADSdir.bat [drive:][path][filename] [/S] [/A[[:]attributes]] [/CSVformat]
возвращает только имена ADS, соответствующиеDIR
подобным параметрам.
Пример использования в PowerShell:
PS D:\PShell> . D:\bat\ADSdisk.bat /CSVformat
"streamName",streamSize,"filePath"
"ADS_disk_root.txt",36,"D:\"
# comment: ADS on D:\ "..:ADS_disk_root.txt:$DATA"
# comment: no ADS on F:\
# comment: no ADS on C:\
# comment: no ADS on E:\
PS D:\PShell> (. D:\bat\ADSdisk.bat /CSVformat) | ConvertFrom-Csv
streamName streamSize filePath
---------- ---------- --------
ADS_disk_root.txt 36 D:\
PS D:\PShell> (. D:\bat\ADSdir.bat d:\ba* /CSVformat) | ConvertFrom-Csv
streamName streamSize filePath
---------- ---------- --------
alternate.data.stream.txt 46 d:\BAsoftwarelist.csv
alternate.data.stream.txt 23 d:\bat
PShell.txt 34 d:\bat
star.bat 12 d:\bat
star.txt 23 d:\bat
PS D:\PShell>
ADSdisk.bat
:
@ECHO OFF
SETLOCAL EnableExtensions DisableDelayedExpansion
set "_keyword=Directory"
set "_CSVformat="
set "_firstLine="
set _filePath=%*
if defined _filePath (
for %%G in ( %_filePath% ) do (
if /I %%G == /CSVformat (
set _filePath=%_filePath:/CSVformat=%
set "_CSVformat=/CSVformat"
)
)
)
set "_property=DeviceID^,DriveLetter^,DriveType^,FileSystem^,SystemName"
for /F "skip=1 tokens=1-4,*" %%G in ('
wmic volume where "FileSystem LIKE '_%%' and DriveLetter LIKE '_:'" get %_property%
') do (
if not "%%H"=="" (
rem echo(# comment: %%H %%I %%J %%G
set "_subFolder="
set "_subDisk=%%~H\"
for /F "delims=" %%g in ( 'dir /B /A:D /A /O:-N "%%~H\"') do set "_subFolder=%%~g"
if defined _subFolder (
call :findADSroot
if not defined _fileName (
call echo(# comment: no ADS on %%_subDisk%%
) else (
call echo(# comment: ADS on %%_subDisk%% "%%_fileName%%"
)
) else (
echo(# comment: no subfoler under "%%~H\"
)
)
)
ENDLOCAL
goto :eof
:findADSroot
set "_pass="
set "_filePath=%_subDisk%%_subFolder%"
rem echo(# comment: ===testing=== "%_filePath%\"
set "_fileName="
for /F "tokens=1,*" %%G in ('
dir /-C /R /S /A "%_filePath%" ^| findstr /I /R "\.\.:.*:\$DATA ^.%_keyword%"
') do (
set "_fileSize="
if "%%~G"=="%_keyword%" (
if defined _pass goto :eof
for /F "tokens=1,*" %%g in ("%%~H") do set "_fileRoot=%%~h"
set /A _pass +=1
) else (
set "_fileSize=%%~G"
set "_fileName=%%~H"
)
if defined _fileSize call :outputDisk
)
goto :eof
:outputDisk
if defined _CSVformat (
REM csv output:
if not defined _firstLine echo "streamName",streamSize,"filePath"
for /F "tokens=1-3 delims=:" %%g in ("%_fileName%") do (
echo "%%~h",%_fileSize%,"%_subDisk%"
)
) else (
REM alternative output: streamSize,"streamFullPath"
echo %_fileSize% "%_subDisk%%_fileName:~2%"
)
set /A _firstLine += 1
goto :eof
ADSdir.bat
:
@ECHO OFF
SETLOCAL EnableExtensions DisableDelayedExpansion
set "_keyword=Directory"
set "_CSVformat="
set "_firstLine="
set _filePath=%*
if defined _filePath (
for %%G in ( %_filePath% ) do (
if /I %%G == /CSVformat (
set _filePath=%_filePath:/CSVformat=%
set "_CSVformat=/CSVformat"
)
)
)
if not defined _filePath set "_filePath=/S "%CD%""
call :findADS
ENDLOCAL
goto :eof
:findADS
for /F "tokens=1,*" %%G in ('
dir /-C /R %_filePath% ^| findstr /I /R ":.*:\$DATA ^.%_keyword%"
') do (
set "_fileSize="
if "%%~G"=="%_keyword%" (
for /F "tokens=1,*" %%g in ("%%~H") do set "_fileRoot=%%~h"
call :backslash
) else (
set "_fileSize=%%~G"
rem for /F "tokens=1,*" %%g in ("%%~G") do
set "_fileName=%%~H"
call :testdots
)
if defined _fileSize call :output
)
goto :eof
:backslash
set "_backslash=%_fileRoot:~-1%"
if "%_backslash%"=="\" (set "_backslash=") else set "_backslash=\"
rem echo %~0 %_fileRoot:~-1%==%_backslash%
rem pause
goto :eof
:testdots
rem "." = a folder itself
if "%_fileName:~0,2%"==".:" set "_fileSize="
rem ".." = parent folder
if "%_fileName:~0,3%"=="..:" set "_fileSize="
goto :eof
:output
if defined _CSVformat (
REM csv output:
if not defined _firstLine echo "streamName",streamSize,"filePath"
for /F "tokens=1-3 delims=:" %%g in ("%_fileName%") do (
echo "%%~h",%_fileSize%,"%_fileRoot%%_backslash%%%~g"
)
) else (
REM alternative output: streamSize,"streamFullPath"
echo %_fileSize% "%_fileRoot%%_backslash%%_fileName%"
)
set /A _firstLine += 1
goto :eof