Begrenzen Sie die Rekursionstiefe von Get-ChildItem

82

Mit diesem Befehl kann ich alle Unterelemente rekursiv abrufen:

Get-ChildItem -recurse

Aber gibt es eine Möglichkeit, die Tiefe zu begrenzen? Wenn ich zum Beispiel nur ein oder zwei Ebenen nach unten rekursieren möchte?

Svish
quelle

Antworten:

109

Verwenden Sie diese Option, um die Tiefe auf 2 zu begrenzen:

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

Die Art und Weise, wie es funktioniert, ist, dass es die Kinder in jeder Tiefe 2,1 und 0 zurückgibt.


Erläuterung:

Dieser Befehl

Get-ChildItem \*\*\*

Gibt alle Elemente mit einer Tiefe von zwei Unterordnern zurück. Durch Hinzufügen von \ * wird ein zusätzlicher Unterordner zum Suchen hinzugefügt.

Um eine rekursive Suche mit get-childitem einzuschränken, müssen Sie gemäß der OP-Frage alle Tiefen angeben, die durchsucht werden können.

CB.
quelle
So genial. Ich glaube, ich musste dies in PowerShell noch nie tun, aber ich weiß, dass ich es mir schon einmal in CMD.EXE gewünscht habe.
Aphorie
15
Scheint, als müssten Sie "-path \ * \ * \ *, \ * \ *, \ *" ausführen, um die Zwischentiefen einzuziehen.
Gerard ONeill
Ich habe es versucht, aber es scheint hoch statt runter zu gehen. Wie kann ich damit einen Ordnerbaum wie unter superuser.com/questions/258287/… generieren ? Vielen Dank.
Royi
2
Um die Rekursion aus dem aktuellen Verzeichnis zu starten, muss am Anfang jedes Pfads ein Punkt hinzugefügt werden. Get-ChildItem .\*\*\*,.\*\*,.\*In PowerShell 5.1 verfügt Get-ChildItem irgendwann über einen -DepthParameter.
beleuchtet
65

Ab Powershell 5.0 können Sie jetzt den -DepthParameter in Get-ChildItem!

Sie kombinieren es mit -Recurse, um die Rekursion zu begrenzen.

Get-ChildItem -Recurse -Depth 2
dee-see
quelle
4
Es scheint, dass der -RecurseSchalter optional / impliziert ist, wenn er -Depthangegeben wird.
Charlie Joynt
7
Eine Sache, die ich dabei gefunden habe und die seltsam erscheint, ist, -Excludewenn sie -Depthden -DepthWert negiert .
ATek
2
@ssaviers Das gleiche Problem tritt auch bei -Include auf.
Eternal21
Für das, was es wert ist, schien der Parameter -Depth beim Kombinieren mit Platzhaltern ignoriert zu werden. Gibt beispielsweise gci c:\*.exe -Depth 1Dateien mit mehreren Unterverzeichnissen zurück.
GuitarPicker
Gut zu wissen! gci c:\ -filter *.exe -depth 1würde dir wahrscheinlich das bringen, was du willst @GuitarPicker Ich habe momentan jedoch keine Windows-Maschine zum Testen
siehe
9

Versuchen Sie diese Funktion:

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

Quelle

walid2mi
quelle
1
Es funktioniert tatsächlich. Beispielaufruf: Get-ChildItemToDepth -ToDepth 2(arbeitet am aktuellen Verzeichnis)
Peter Mortensen
1

Ich habe versucht, die Rekursionstiefe von Get-ChildItem mithilfe von Resolve-Path zu begrenzen

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

Aber das funktioniert gut:

gci "$PATH\*\*\*\*"
scanlegentil
quelle
1

Dies ist eine Funktion, die eine Zeile pro Element mit Einrückung entsprechend der Tiefenstufe ausgibt. Es ist wahrscheinlich viel besser lesbar.

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

Es basiert auf einem Blogbeitrag, Practical PowerShell: Bereinigen von Dateibäumen und Erweitern von Cmdlets .

sancho.s ReinstateMonicaCellio
quelle
0

@scanlegentil Ich mag das.
Eine kleine Verbesserung wäre:

$Depth = 2
$Path = "."

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

Wie bereits erwähnt, würde dies nur die angegebene Tiefe scannen, daher ist diese Änderung eine Verbesserung:

$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
quelle
Dies wird alle Unterordnernamen bis zur angegebenen Tiefe
anzeigen
1
Dies scheint Elemente in einer bestimmten Tiefe anzuzeigen, nicht bis zu einer bestimmten Tiefe.
sancho.s ReinstateMonicaCellio