Ogranicz głębokość rekursji Get-ChildItem


82

Mogę uzyskać wszystkie elementy podrzędne rekurencyjnie za pomocą tego polecenia:

Get-ChildItem -recurse

Ale czy istnieje sposób na ograniczenie głębokości? Czy chcę na przykład powtórzyć tylko jeden lub dwa poziomy w dół?

Odpowiedzi:


109

Użyj tego, aby ograniczyć głębokość do 2:

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

Sposób działania polega na tym, że zwraca dzieci na każdej głębokości 2,1 i 0.


Wyjaśnienie:

To polecenie

Get-ChildItem \*\*\*

zwraca wszystkie elementy o głębokości dwóch podfolderów. Dodanie \ * dodaje dodatkowy podfolder do wyszukiwania.

Zgodnie z pytaniem OP, aby ograniczyć wyszukiwanie rekurencyjne za pomocą get-childitem, musisz określić wszystkie głębokości, które można przeszukiwać.


Niesamowite. Wydaje mi się, że nigdy nie musiałem tego robić w PowerShell, ale wiem, że chciałem tego wcześniej w CMD.EXE.
aforia

15
Wydaje się, że musisz wykonać „-path \ * \ * \ *, \ * \ *, \ *”, aby wciągnąć pośrednie głębokości.
Gerard ONeill

Próbowałem, ale wydaje się, że idzie w górę zamiast w dół. Jak mogę go użyć do wygenerowania drzewa folderów, jak w superuser.com/questions/258287/… ? Dziękuję Ci.
Royi,

2
Aby rozpocząć rekursję z bieżącego katalogu, należy dodać kropkę na początku każdej ścieżki. Get-ChildItem .\*\*\*,.\*\*,.\*W pewnym momencie w programie PowerShell 5,1 Get-ChildItem ma teraz -Depthparametr.
świeci

65

Począwszy od programu PowerShell 5.0 , możesz teraz używać -Depthparametru w Get-ChildItem!

Łączysz to z, -Recurseaby ograniczyć rekursję.

Get-ChildItem -Recurse -Depth 2

4
Wydaje się, że -Recurseprzełącznik jest opcjonalny / domniemany, gdy -Depthjest określony.
Charlie Joynt

7
Jedna rzecz, którą zauważyłem w tym, wydaje się dziwna, to -Excludegdy dołączona do -Depthneguje -Depthwartość.
ATek

2
@ssaviers Ten sam problem występuje również z -Include.
Eternal 21

Z tego powodu parametr -Depth wydawał się być ignorowany podczas łączenia z symbolami wieloznacznymi. Na przykład gci c:\*.exe -Depth 1zwraca pliki głęboko w wielu podkatalogach.
GuitarPicker

Dobrze wiedzieć! gci c:\ -filter *.exe -depth 1prawdopodobnie dostaniesz to, czego chcesz @GuitarPicker Nie mam teraz komputera z systemem Windows do przetestowania
zobacz

9

Wypróbuj tę funkcję:

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

źródło


1
To faktycznie działa. Przykładowe wywołanie: Get-ChildItemToDepth -ToDepth 2(praca nad bieżącym katalogiem)
Peter Mortensen

1

Próbowałem ograniczyć głębokość rekursji Get-ChildItem za pomocą Resolve-Path

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

Ale to działa dobrze:

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

1

Jest to funkcja, która generuje jeden wiersz na element, z wcięciem zależnym od poziomu głębokości. Prawdopodobnie jest znacznie bardziej czytelny.

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

Opiera się na poście na blogu, Praktyczny program PowerShell: czyszczenie drzew plików i rozszerzanie poleceń cmdlet .


0

@scanlegentil Podoba mi się to.
Mała poprawa byłaby:

$Depth = 2
$Path = "."

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

Jak wspomniano, skanowałoby to tylko określoną głębokość, więc ta modyfikacja jest ulepszeniem:

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

Spowoduje to wyświetlenie wszystkich nazw podfolderów do określonej głębokości
kevro

1
Wydaje się, że pokazuje elementy na określonej głębokości, a nie na określonej głębokości.
sancho.s ReinstateMonicaCellio
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.