Войти

Показать полную графическую версию : Обработка путей превышающих 260 символов


pogo
08-12-2015, 21:27
Доброго времени суток.
Помогите пожалуйста допилить скрипт, для обработки путей больше 260 символов.

$path = "c:\f1"
$logfile = "C:\f1\log.txt"
if (!(Test-Path $path)) {
Write-Host "Folder not found" -ForegroundColor Red
break
}
$folder_list = Get-ChildItem -Path $path -Recurse -Directory
foreach ($folder in $folder_list) {
#$ACL = Get-Acl $folder.PSPath
$ACL = Get-Acl $folder.FullName
if ($ACL.AreAccessRulesProtected -ne $false) {
$str = $folder.fullname
Add-Content -Value $str -Path $logfile
}
}

Вычитал что вроде как это решается монтированием. Попробовал на тестовом скрипте, но что-то он отказывается работать.

Remove-PSDrive -Name X
$rootpath = "C:\test"
$logfile = "c:\test\log.txt"
try {
$folder_list = Get-ChildItem $rootpath -Recurse -Directory -ErrorAction Stop
foreach ($folder in $folder_list) {
$folder.Name
Write-Host "+++++++"
$folder.FullName
Write-Host "-------"
$folder.PSPath
Write-Host "========================="
($folder.PSPath).Length
Write-Host "\\\\\\\\\\\"
}
}
catch {
Write-Host "ERROR"
$folder.FullName
($folder.FullName).Length
$newrootfolder = New-PSDrive -Name X -PSProvider FileSystem -Root $folder.FullName
Get-ChildItem $newrootfolder
}

И в последней строке Get-ChildItem $newrootfolder скрипт вываливается в ошибку длинного пути.
Подскажите пожалуйста, в чём может быть проблема?

Kazun
09-12-2015, 00:10
Утилита SetAcl (https://helgeklein.com/download/) не имеет таких ограничений:

$folders = SetACL.exe -on "C:\f1" -ot file -actn list -rec cont | Where {$_ -match "(:\\|DACL\()"}

$log = for($i =0 ; $i -le $folders.count;$i+=2) {
$status = $folders[($i+1)] -notmatch "not_protected"
if($status)
{
$folders[$i]
}
}
$log | Out-File $logfile

greg zakharov
09-12-2015, 13:23
Kazun, вроде бы тот же robocopy умеет работать с путями в более 260 символов, да и трюк с dir тоже прокатывает, например:PS E:\sandbox> cmd /c dir \\e:\test /s /b | findstr ...Что-то в этом роде. Но, если не хочется использовать консоль в хосте, можно попытать счастья со сторонними библиотеками, вроде AlphaFS (https://github.com/alphaleonis/AlphaFS) и QuickIO (https://github.com/SchwabenCode/QuickIO), - обе с открытым исходным кодом. Ну и наконец можно поробовать использовать методы GetFiles() и GetDirectories из типа System.IO.Directory.

pogo
09-12-2015, 13:40
Спасибо за ответы.

Kazun,
Приведённый Вами скрипт не работает
второй строгой добавил
write-host folders: $folders
что бы посмотреть что утилита получает, и после вывода ошибка.

folders:
Cannot index into a null array.
At line:6 char:2
+ $status = $folders[($i+1)] -notmatch "not_protected"
....

greg zakharov,
robocopy может и умеет, но она ничего не знает о правах и их наследованиях.
Как показано в первом посте, я попробовал обрезать пути, методом монтирования диска, как пишут в google, но у меня это не работает..

Kazun
09-12-2015, 14:03
Какой результат вывода?
SetACL.exe -on "C:\f1" -ot file -actn list -rec cont

pogo
09-12-2015, 14:37
C:\test> .\SetACL.exe -on "C:\test" -ot file -actn list -rec cont
C:\test\very_bif_test_folder_001\very_bif_test_folder_002\very_bif_test_folder_003\very_bif_test_fol der_004

DACL(protected+auto_inherited):
SYSTEM full allow container_inherit+object_inherit
Administrators full allow container_inherit+object_inherit
Users read_execute allow container_inherit+object_inherit
Users FILE_ADD_FILE+FILE_ADD_SUBDIRECTORY allow container_inherit
CREATOR OWNER full allow container_inherit+object_inherit+inherit_only


SetACL finished successfully.

pogo
09-12-2015, 14:57
Kazun,

Прошу прощения.
По ходе дела я где-то в путях накосячил, из-за этого не работало.
Вот рабочий вариант

$logfile = "C:\test\log.txt"
$folders = C:\test\SetACL.exe -on "C:\test" -ot file -actn list -rec cont | Where {$_ -match "(:\\|DACL\()"}

#write-host folders: $folders

$log = for($i=0 ; $i -le $folders.count; $i+=2) {
$status = $folders[($i+1)] -notmatch "not_protected"
if($status)
{
$folders[$i]
}
}

$log | Out-File $logfile

Большое спасибо!!

pogo
10-12-2015, 09:10
Подскажите, а можно сделать тоже самое, но средствами утилиты от MS - SubInACL?

Kazun
10-12-2015, 09:44
$subinacl = "C:\Program Files (x86)\Windows Resource Kits\Tools\subinacl.exe"
$logname = "C:\log.txt"
$folder = "C:\f1"

& $subinacl /outputlog=$logname /subdirectories=directories $folder
$folders = (Get-Content $logname) -match "(\+File|/control)"

$log = for($i=0 ; $i -le $folders.count; $i+=2) {
$status = $folders[($i+1)] -match "SE_DACL_PROTECTED"
if($status)
{
$folders[$i].TrimStart("+File ")
}
}
$log | Out-File $logfile

pogo
10-12-2015, 10:01
Kazun, спасибо за оперативный ответ!
Скрипт отрабатывает без ошибок, но лог файл пустой.

P.S. Вроде как проблему решил, указав такой путь
$folder = "C:\f1\*"

pogo
29-12-2015, 16:12
На удивление, ни один из вариантов, как оказалось, не заработал с UNC и DFS путями ((
Как сказал всем известный поисковик, subinacl вообще не понимает dfs.
SetACL понимает и UNC и DFS, но вывод получается примерно такой:
folders[0]: DACL(protected):
folders[6]: DACL(not_protected):
Подскажите, как подправить скрипты, пожалуйста, пока сам в ключах утилиты не разобрался..

Kazun
30-12-2015, 13:33
Качаем модуль - https://gallery.technet.microsoft.com/scriptcenter/1abd77a5-9c0b-4a2b-acef-90dbb2b84e85

Get-ChildItem2 -Path $folder -Recurse -Directory | Where {!(Get-NTFSInheritance $_).AccessInheritanceEnabled} | Select -ExpandProperty FullName

pogo
30-12-2015, 14:31
Kazun,
Большое спасибо за все ответы в теме! :)
Интересный модуль, изучим-с) Странно, что во время поиска не наткнулся на него.
В попытках завести один из предложенных Вами вариантов выше, заработал тот, что использует subinacl, ниже рабочий вариант с unc.

cls
$subinacl = "C:\temp\subinacl.exe" #путь до улититы subinacl.exe
$log = "c:\temp\log.txt" #путь до лог файла
$log_subinacl = "c:\temp\log_subinacl.txt" #путь до внутреннего лог файла subinacl
$path = "\\uncpath...\*" #корневая папка для поиска

& $subinacl /outputlog=$log_subinacl /subdirectories=directories $path #запуск subinacl в фоне, с записью инфы в лог
$content = (Get-Content $log_subinacl) -match "(\+File|\/control)" #выбираем из файла строки по условию

$result = for($i=0; $i -le $content.Count; $i+=2) {
$status = $content[$i+1] -match "SE_DACL_PROTECTED" #если в строке, есть подстрока, записываем в переменную
if($status) {
$content[$i].TrimStart("+File ") #удаляем указанную подстроку из строки
}
}

Remove-Item $log_subinacl #удаляем лог subinacl
$result | Out-File $log #записываем результат в переменную
На win10 работал подобный вариант написанный Вами ранее, но на win serv 2012r2 регулярное выражение должно выглядеть так - (\+File|\/control).
P.S. Но приведённый Вами модуль, мне нравится большей, этих костыльных решений )




© OSzone.net 2001-2012