Обмежити глибину рекурсії Get-ChildItem


82

Я можу отримати всі підпункти рекурсивно, використовуючи цю команду:

Get-ChildItem -recurse

Але чи є спосіб обмежити глибину? Якщо я хочу лише повторити один або два рівні, наприклад?

Відповіді:


109

Використовуйте це, щоб обмежити глибину до 2:

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

Це працює так, що повертає дітей на кожну глибину 2,1 та 0.


Пояснення:

Ця команда

Get-ChildItem \*\*\*

повертає всі елементи глибиною до двох підпапок. Додавання \ * додає додаткову підпапку для пошуку.

Відповідно до запитання OP, щоб обмежити рекурсивний пошук за допомогою get-childitem, вам потрібно вказати всі глибини, які можна шукати.


Такий чудовий. Думаю, мені ніколи не потрібно було робити це в PowerShell, але я знаю, що раніше цього бажав у CMD.EXE.
афорія

15
Здається, вам потрібно зробити "-path \ * \ * \ *, \ * \ *, \ *", щоб втягнути проміжні глибини.
Gerard ON, до

Я спробував, але, схоже, він піднімається вгору, а не вниз. Як я можу використовувати його для створення дерева папок, як у superuser.com/questions/258287/… ? Дякую.
Рої

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вказано.
Charlie Joynt

7
Одне, що я виявив із цим, що здається дивним, - це те, -Excludeколи воно входить до складу -Depthзаперечує -Depthзначення.
АТек

2
@ssaviers Така сама проблема трапляється і з -Include.
Eternal21,

Наскільки це варте, параметр -Depth, здавалося, ігнорувався при комбінуванні з підстановними символами. Наприклад, gci c:\*.exe -Depth 1повертає файли в глибину декількох підкаталогів.
GuitarPicker

Добре знати! gci c:\ -filter *.exe -depth 1напевно, ви отримаєте те, що хочете @GuitarPicker У мене зараз немає машини для тестування Windows, однак
дивіться

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
            }
        }
    }
}

Він заснований на дописі в блозі Practical 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
}

Це покаже всі імена
підпапок

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