PowerShell удаляет рекурсивную переменную из полного пути

У меня есть простой скрипт, который ходит по дереву каталогов.

function GetSubFolders([IO.DirectoryInfo]$folder) {
    Write-Host "Getting folder $folder"

    Get-ChildItem $folder | ? { $_.PSIsContainer } | % { GetSubFolders $_ }
}

Если я вызову GetSubFolders "c:\temp", произойдет сбой для каждого подкаталога, найденного в c:\temp:

Get-ChildItem: не удается найти путь 'C:\WINDOWS\system32\somefolder

Где «somefolder» — это подкаталог c:\temp. Переменная $_ явно является объектом System.IO.DirectoryInfo, но почему она лишена своего абсолютного пути и внезапно сделана относительно текущего каталога, c:\windows\system32? Обратите внимание, что при входе в этот метод он правильно выводит

Получение папки c:\temp

Это означает, что он работает один раз, поэтому не может быть проблем с Get-ChildItem, принимающим объект DirectoryInfo в качестве параметра.


person Dan    schedule 17.01.2019    source источник
comment
вы пытались использовать объект по имени или по положению, которое ТОЛЬКО соответствует -Name свойству Get-ChildItem. [ухмылка] взгляните на этот [io.directoryinfo]'C:\temp' | Select-Object -Property * и затем сравните его со списком из этого (Get-Help Get-ChildItem -Parameter *).Name. обратите внимание на отсутствие имени свойства -Path или -LiteralPath` в 1-м объекте.   -  person Lee_Dailey    schedule 18.01.2019
comment
Тогда почему это срабатывает один раз, вот почему я озадачен.   -  person Dan    schedule 19.01.2019
comment
я не знаю ... мне всегда кажется, что это не удается.   -  person Lee_Dailey    schedule 19.01.2019


Ответы (3)


function GetSubFolders([IO.DirectoryInfo]$folder) {
    Write-Host "Getting folder $folder"
    Get-ChildItem $folder | ? { $_.PSIsContainer } | % { GetSubFolders $_.FullName }
}

Я думаю, вы ищете собственность FullName.

person Victor Dronov    schedule 18.01.2019
comment
Это то, что я использовал в качестве обходного пути, но если $_ является объектом directoryinfo, зачем вообще требуется .FullName? - person Dan; 19.01.2019
comment
powershell, работающий с объектами. Каждый объект имеет более 1 свойства (обычно). Поэтому некоторые из них должны возвращать одно из них (свойство) в качестве значения по умолчанию в определенных сценариях, таких как ваш. Значением по умолчанию в вашем случае будет имя, но не полное имя. - person Victor Dronov; 19.01.2019
comment
В противном случае, поскольку ваша конструкция может работать, используйте $folder.fullname в начале вместо $_.fullname в конце. - person Victor Dronov; 19.01.2019
comment
1 другой способ: (gci $folder -recurse | где {$_.mode -like 'd*'}).fullname | Сортировать - person Victor Dronov; 19.01.2019

Попробуйте использовать

Get-ChildItem -Path 'c:\temp' -Recurse -Directory

Флаг каталога будет доступен в V3. Если вы не используете V3, вы также можете использовать

Get-ChildItem -Path 'c:\temp' -Recurse | ? { $_.PSIsContainer }

Редактировать:

Флаг каталога доступен в V3. Спасибо, Ансгар Вихерс, за ваш комментарий.

person Dejulia489    schedule 17.01.2019

Решение с рекурсией/каналами довольно неэффективно. Как и другие, лучше использовать переключатель -recurse с GCI. Но есть и альтернатива с циклом/очередью. Это будет работать для любого типа древовидного объекта — прокручивайте дочерние элементы корневого узла, и если дочерний узел имеет больше узлов, добавьте его в очередь.

function Get-SubfolderQueue { param([IO.directoryinfo]$dir)

 $queue = New-Object System.Collections.Queue
 $queue.Enqueue($dir)

 While($queue.Count -gt 0) {
    $curr = $queue.Dequeue()
    foreach ($d in $curr.GetDirectories()) {
        Write-Output $d
        If($d.GetDirectories().Count -gt 0) { 
           $queue.Enqueue($d)
         }
    }
 }

}
person Mike Twc    schedule 18.01.2019