Centrum skryptów - Systemy operacyjne

Jak utworzyć listę wszystkich podfolderów zawartych w folderze i umieścić ją w tablicy?

Udostępnij na: Facebook

Skrypciarze odpowiadają na Wasze pytania

Cześć Skrypciarze!

Witamy w rubryce TechNet, w której Skrypciarze z firmy Microsoft odpowiadają na częste pytania dotyczące używania skryptów w administracji systemu. Jeśli macie jakieś pytania z tej dziedziny, zachęcamy do wysłania e-maila na adres: scripter@microsoft.com. Nie możemy zagwarantować odpowiedzi na każde otrzymane pytanie, ale staramy się jak możemy.

Jak utworzyć listę wszystkich podfolderów zawartych w folderze i umieścić ją w tablicy?

Cześć Skrypciarze! Pytanie

Cześć, Skrypciarze! Jak utworzyć listę wszystkich podfolderów zawartych w folderze i umieścić ją w tablicy?

-- PW

Cześć Skrypciarze! Odpowiedź

Cześć, PW. Wiemy, że wszyscy nasi czytelnicy z niepokojem czekają na informację, czy Skrypciarzom udało się bez kłopotów przenieść z budynku 43 do budynku 42 (znajdującego się naprzeciwko starego biurowca). No cóż, na pewno się przenieśliśmy, ale nie wiemy, czy można powiedzieć, że udało się to bez kłopotów. I tak, przed przeprowadzką musieliśmy wypełnić „Kwestionariusz przeprowadzki”, zawierający na przykład takie dwa pytania:

  • Ile szafek kartotekowych na kółkach potrzebujesz?
  • Ile półek na książki potrzebujesz?

Skrypciarz piszący te słowa zgłosił zapotrzebowanie tylko na jedną półkę na książki, nie zamówił natomiast szafek kartotekowych. Zgadnijcie, co dostał? No tak, czyżby Wam też przeprowadzkę organizował Microsoft? To oczywiste – nie dostał półki na książki, ale za to otrzymał szafkę kartotekową. Zostawiono mu także na biurku notkę: „Pana komputer i urządzenia peryferyjne nie były podłączone w starym biurze, więc nie podłączaliśmy ich ponownie”. Nie żeby podłączenie paru kabli było jakąś filozofią (szczególnie dla Skrypciarza!), ale jednak dałby głowę, że cały sprzęt w starym biurze był podłączony – Skrypciarz na błędach przekonał się, że komputery działają o wiele lepiej, kiedy wtyczki tkwią tam, gdzie powinny, zamiast walać się po podłodze.

Możliwe rzecz jasna, że Skrypciarz po prostu nie zna właściwego znaczenia słowa „podłączyć”.

Aha, nie działa też telefon Skrypciarza. Tak mu się przynajmniej zdawało. Jednak pracownik odpowiedzialny za telefony sprawdził na swojej liście, a że telefonu Skrypciarza na niej nie było, doszedł do wniosku, że musi działać. Fajnie, przepraszam, że zawracałem głowę.

Nieważne. Tak czy inaczej, Skrypciarze wracają. A jeśli nam nie wierzycie, to się przekonajcie: oto skrypt pobierający listę wszystkich podfolderów danego foldera i tworzy z nich tablicę:

On Error Resume Next



Dim arrFolders()

intSize = 0



strComputer = "."

Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")



strFolderName = "c:\scripts"



Set colSubfolders = objWMIService.ExecQuery _

    ("Associators of {Win32_Directory.Name='" & strFolderName & "'} " _

        & "Where AssocClass = Win32_Subdirectory " _

            & "ResultRole = PartComponent")



ReDim Preserve arrFolders(intSize)

arrFolders(intSize) = strFolderName

intSize = intSize + 1



For Each objFolder in colSubfolders

    GetSubFolders strFolderName

Next



Sub GetSubFolders(strFolderName)

    Set colSubfolders2 = objWMIService.ExecQuery _

        ("Associators of {Win32_Directory.Name='" & strFolderName & "'} " _

            & "Where AssocClass = Win32_Subdirectory " _

                & "ResultRole = PartComponent")



    For Each objFolder2 in colSubfolders2

        strFolderName = objFolder2.Name

        ReDim Preserve arrFolders(intSize)

        arrFolders(intSize) = strFolderName

        intSize = intSize + 1

        GetSubFolders strFolderName

    Next

End Sub



For Each strFolder in arrFolders

    Wscript.Echo strFolder

Next

Nie mylicie się – jest to skrypt z gatunku skomplikowanych. A to dlatego, że musieliśmy zastosować podprogram rekursywny. Nie ma żartów: podprogram rekursywny (czyli taki, który może uruchomić sam siebie) to nieco złożone pojęcie i nie mamy tutaj miejsca, aby je wyjaśniać. Odsyłamy więc do odpowiedniego rozdziału (j.ang.) przewodnika Microsoft Windows 2000 Scripting Guide.

Spróbujemy jednak wyjaśnić zasadę działania naszego skryptu. Najpierw za pomocą poniższego wiersza kodu zakładamy tablicę dynamiczną o nazwie arrFolders; jak się można domyślić, będziemy w niej przechowywać listę folderów:

Dim arrFolders()

Następnie przypisujemy wartość 0 zmiennej o nazwie intSize; zmienna ta posłuży nam do mierzenia wielkości naszej tablicy dynamicznej, a także do jej powiększania.

Po połączeniu z usługą WMI komputera lokalnego (chociaż skrypt ten działa równie dobrze na komputerze zdalnym), za pomocą poniższego fragmentu kodu łączymy się z folderem C:\Scripts:

strFolderName = "c:\scripts"



Set colSubfolders = objWMIService.ExecQuery _

    ("Associators of {Win32_Directory.Name='" & strFolderName & "'} " _

        & "Where AssocClass = Win32_Subdirectory " _

            & "ResultRole = PartComponent")

Teraz jesteśmy gotowi do działania. Mamy tablicę dynamiczną o nazwie arrFolders, ale jest ona niestety pusta. Tak więc pierwsze, co musimy zrobić, to podłączyć do niej nasz folder źródłowy C:\Scripts:

ReDim Preserve arrFolders(intSize)

arrFolders(intSize) = strFolderName

intSize = intSize + 1

Jak widać, za pomocą polecenia Redim Preserve zmieniamy wielkość tablicy. Jaka wielkość nas interesuje? Wielkość równa 0 – używamy do tego zmiennej intSize. (No tak. Ale pamiętajmy, że wielkość 0 oznacza, że w tablicy zmieści się jeden element. Tablica wielkości 1 pomieści dwa elementy itd.) Teraz do tablicy dodajemy ścieżkę interesującego nas folderu (zapisaną w zmiennej strFolderName), i zwiększamy wartość zmiennej intSize o 1. Na razie idzie gładko.

Dochodzimy do poniższych trzech wierszy kodu:

For Each objFolder in colSubfolders

    GetSubFolders strFolderName

Next

Wywołujemy w nich rekursywny podprogram GetSubFolders, o którym była mowa wcześniej. Musimy to zrobić, ponieważ WMI samo z siebie zwraca tylko informację o „pierwszej warstwie” podfolderów – np. folder C:\Scripts\ADSI, ale już nie C:\Scripts\ADSI\Users czy C:\Scripts\ADSI\Groups. Dlatego musimy osobno łączyć się z wszystkimi podfolderami, a następnie z ich podfolderami; innymi słowy, uzyskawszy kolekcję podfolderów, musimy sprawdzić, czy one z kolei nie zawierają dalszych podfolderów. Nie wdając się zanadto w szczegóły, do tego właśnie służy nam podprogram rekursywny. Sprawdzi on zawartość każdego podfolderu, każdego pod-podfolderu, każdego pod-pod-podfolderu itd. Dzięki temu uzyskamy kompletne drzewo, uwzględniające wszystkie podfoldery zawarte w C:\Scripts.

A oto nasz podprogram rekursywny:

Sub GetSubFolders(strFolderName)

    Set colSubfolders2 = objWMIService.ExecQuery _

        ("Associators of {Win32_Directory.Name='" & strFolderName & "'} " _

            & "Where AssocClass = Win32_Subdirectory " _

                & "ResultRole = PartComponent")



    For Each objFolder2 in colSubfolders2

        strFolderName = objFolder2.Name

        ReDim Preserve arrFolders(intSize)

        arrFolders(intSize) = strFolderName

        intSize = intSize + 1

        GetSubFolders strFolderName

    Next

End Sub

Jak zapowiadaliśmy, pomijamy opis jego działania. Zwróćmy jednak uwagę na użycie identycznej kwerendy Associators Of, co w wypadku kolekcji „pierwszej warstwy” podfolderów C:\Scripts. Jeśli kwerenda ta zwróci nam jakieś dane, uruchomiona zostanie pętla For Each, która przejdzie przez całą kolekcję. W ramach pętli dodajemy do tablicy ścieżki folderów (znów mamy tam polecenie Redim Preserve), po czym wywołujemy podprogram GetSubFolders. Dlaczego? W celu określenia, czy podfolder zawiera podfoldery niższego rzędu.

Przyznajemy, że jest to dla nas bardzo dezorientujące. Na szczęście jednak VBScript nie daje się tak łatwo zbić z tropu. To chyba jeden z niewielu wypadków, gdy można zdać się na VBScript, samemu się nie przejmując.

Teraz pozostało nam tylko wyświetlić listę wszystkich ścieżek dodanych do tablicy arrFolders. Posłuży nam do tego poniższy fragment kodu:

For Each strFolder in arrFolders

    Wscript.Echo strFolder

Next

Przekonajcie się sami, czy zadziała.

Mamy nadzieję, że o to Ci chodziło, PW. A swoją drogą, Skrypciarz piszący te słowa najprawdopodobniej właśnie odkrył, dlaczego naprawdę jego komputer i inne urządzenia nie zostały podłączone: jednostka centralna jego desktopa jest obecnie w czterech kawałkach, z których jeden jest wyraźnie wygięty. Skrypciarz piszący te słowa nie zna się wprawdzie na sprzęcie, ale zdążył się zorientować, że komputery są sporo sprawniejsze, kiedy wszystkie części są na swoich miejscach i żadna z nich nie jest powyginana. Całkiem możliwe, że do przenoszenia komputerów lepiej używać rąk, a nie nóg.

Ale może nie. W końcu, to byli eksperci.

Uwaga wydawcy: Ktoś musiał donieść firmie od przeprowadzek, kto jest jej klientem. Cały sprzęt należący do Wydawcy Skrypciarzy został przeniesiony bez najmniejszych uszkodzeń. Dostarczono jej także odpowiednią liczbę półek i szafek (po dwie), jak również działający telefon. Wydawca Skrypciarzy nie ma pojęcia, co stało za problemami przy przeprowadzce Skrypciarza. Serio.

 Do początku strony Do początku strony

Centrum skryptów - Systemy operacyjne