Ограничить глубину рекурсии Get-ChildItem


82

Я могу рекурсивно получить все подпункты с помощью этой команды:

Get-ChildItem -recurse

Но есть ли способ ограничить глубину? Если я хочу, например, вернуться на один или два уровня вниз?

Ответы:


109

Используйте это, чтобы ограничить глубину до 2:

Get-ChildItem \*\*\*,\*\*,\*

Это работает так: он возвращает потомков на каждой глубине 2,1 и 0.


Пояснение:

Эта команда

Get-ChildItem \*\*\*

возвращает все элементы с глубиной в две подпапки. Добавление \ * добавляет дополнительную подпапку для поиска.

В соответствии с вопросом OP, чтобы ограничить рекурсивный поиск с использованием get-childitem, вам необходимо указать все глубины, на которых можно выполнять поиск.


Так круто. Думаю, мне никогда не приходилось делать это в PowerShell, но я знаю, что раньше хотел этого в CMD.EXE.
aphoria 06

15
Похоже, вам нужно сделать "-path \ * \ * \ *, \ * \ *, \ *", чтобы втянуть промежуточные глубины.
Gerard ONeill

Я пробовал, но вроде идет вверх, а не вниз. Как я могу использовать его для создания дерева папок, как указано в superuser.com/questions/258287/… ? Благодарю вас.
Royi

2
Чтобы начать рекурсию из текущего каталога, необходимо добавить точку в начале каждого пути. Get-ChildItem .\*\*\*,.\*\*,.\*В какой-то момент в PowerShell 5.1 Get-ChildItem теперь имеет -Depthпараметр.
загорелся

65

Начиная с powershell 5.0 , теперь вы можете использовать -Depthпараметр в Get-ChildItem!

Вы комбинируете его с, -Recurseчтобы ограничить рекурсию.

Get-ChildItem -Recurse -Depth 2

4
Кажется, что -Recurseпереключатель является необязательным / подразумевается, когда -Depthон указан.
Чарли Джойнт,

7
Одна вещь, которую я обнаружил при этом, которая кажется странной, заключается в том, -Excludeчто включение с -Depthотрицает -Depthзначение.
ATek

2
@ssaviers Та же проблема возникает и с -Include.
Eternal21

Как бы то ни было, параметр -Depth, казалось, игнорировался при объединении с подстановочными знаками. Например, gci c:\*.exe -Depth 1возвращает файлы в несколько подкаталогов в глубину.
GuitarPicker

Хорошо знать! gci c:\ -filter *.exe -depth 1вероятно, вы получите то, что вы хотите @GuitarPicker У меня сейчас нет Windows-машины для тестирования
dee-see

9

Попробуйте эту функцию:

Function Get-ChildItemToDepth {
    Param(
        [String]$Path = $PWD,
        [String]$Filter = "*",
        [Byte]$ToDepth = 255,
        [Byte]$CurrentDepth = 0,
        [Switch]$DebugMode
    )

    $CurrentDepth++
    If ($DebugMode) {
        $DebugPreference = "Continue"
    }

    Get-ChildItem $Path | %{
        $_ | ?{ $_.Name -Like $Filter }

        If ($_.PsIsContainer) {
            If ($CurrentDepth -le $ToDepth) {

                # Callback to this function
                Get-ChildItemToDepth -Path $_.FullName -Filter $Filter `
                  -ToDepth $ToDepth -CurrentDepth $CurrentDepth
            }
            Else {
                Write-Debug $("Skipping GCI for Folder: $($_.FullName) " + `
                  "(Why: Current depth $CurrentDepth vs limit depth $ToDepth)")
            }
        }
    }
}

источник


1
Это действительно работает. Пример вызова: Get-ChildItemToDepth -ToDepth 2(работает в текущем каталоге)
Питер Мортенсен

1

Я пытался ограничить глубину рекурсии Get-ChildItem с помощью Resolve-Path

$PATH = "."
$folder = get-item $PATH 
$FolderFullName = $Folder.FullName
$PATHs = Resolve-Path $FolderFullName\*\*\*\
$Folders = $PATHs | get-item | where {$_.PsIsContainer}

Но это нормально работает:

gci "$PATH\*\*\*\*"

1

Это функция, которая выводит по одной строке для каждого элемента с отступом в соответствии с уровнем глубины. Вероятно, это гораздо более читабельно.

function GetDirs($path = $pwd, [Byte]$ToDepth = 255, [Byte]$CurrentDepth = 0)
{
    $CurrentDepth++
    If ($CurrentDepth -le $ToDepth) {
        foreach ($item in Get-ChildItem $path)
        {
            if (Test-Path $item.FullName -PathType Container)
            {
                "." * $CurrentDepth + $item.FullName
                GetDirs $item.FullName -ToDepth $ToDepth -CurrentDepth $CurrentDepth
            }
        }
    }
}

Он основан на сообщении в блоге « Практическая оболочка PowerShell: сокращение файловых деревьев и расширение командлетов» .


0

@scanlegentil Мне это нравится.
Небольшое улучшение было бы:

$Depth = 2
$Path = "."

$Levels = "\*" * $Depth
$Folder = Get-Item $Path
$FolderFullName = $Folder.FullName
Resolve-Path $FolderFullName$Levels | Get-Item | ? {$_.PsIsContainer} | Write-Host

Как уже упоминалось, это будет сканировать только указанную глубину, поэтому эта модификация является улучшением:

$StartLevel = 1 # 0 = include base folder, 1 = sub-folders only, 2 = start at 2nd level
$Depth = 2      # How many levels deep to scan
$Path = "."     # starting path

For ($i=$StartLevel; $i -le $Depth; $i++) {
    $Levels = "\*" * $i
    (Resolve-Path $Path$Levels).ProviderPath | Get-Item | Where PsIsContainer |
    Select FullName
}

Это покажет все имена подпапок до указанной глубины
kevro

1
Кажется, что элементы отображаются на заданной глубине, а не на заданной глубине.
sancho.s ReinstateMonicaCellio
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.