Centrum Skryptów - Systemy Operacyjne

Jak sprawdzić, czy któreś z plików w folderze były modyfikowane w ciągu ostatnich 90 dni?

Udostępnij na: Facebook

Skrypciarze odpowiadają na Wasze pytania

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 sprawdzić, czy któreś z plików w folderze były modyfikowane w ciągu ostatnich 90 dni?

Cześć, Skrypciarze! Chcę okresowo sprawdzać na moich plikach serwerów, czy jakieś foldery lub ich podfoldery zawierają pliki, które nie są aktualizowane. A konkretnie, chcę sprawdzać, czy zmodyfikowano którykolwiek z plików w danym folderze w ciągu ostatnich 90 dni. Jeżeli znajdę folder, który nie został ostatnio zmodyfikowany, chcę, aby skrypt wywołał echo ścieżki tego folderu. Jak napisać skrypt, który to zrobi?

-- MM

Cześć, MM. Dzisiaj publikujemy ostatni artykuł rubryki Cześć, Skrypciarze w 2007 roku; zobaczymy się znowu 2 stycznia 2008 r. Z uwagi na właśnie ten fakt, że Święta za pasem, wybaczcie mi, ale nie będzie dziś żadnej opowieści – jesteśmy tak strasznie zawaleni robotą, że brakuje nam na to czasu. Obiecuje, że nadrobię to w przyszłym roku.

A teraz bierzmy się za skrypt, który sprawdza pliki w folderze (i jego podfolderach) i przekazuje informacje na temat folderów, które zawierają wyłącznie stare pliki; czyli foldery, w których pliki nie były modyfikowane od 90 dni. Oto i on:

Set objFSO = CreateObject("Scripting.FileSystemObject")



Set objStartFolder = objFSO.GetFolder("C:\Scripts")

Set colFiles = objStartFolder.Files



i = 0



For Each objFile in colFiles

    dtmDate = objFile.DateLastModified

    intAge = DateDiff("d", dtmDate, Date)

    If intAge < 90 Then

        i = 1

        Exit For

    End If

Next



If i = 0 Then

    Wscript.Echo objStartFolder.Path

End If



ShowSubfolders(objStartFolder) 



Sub ShowSubFolders(Folder)

    For Each objSubfolder in Folder.SubFolders

        Set objFolder = objFSO.GetFolder(objSubFolder.Path)

        Set colFiles = objFolder.Files



        i = 0



        For Each objFile in colFiles

            dtmDate = objFile.DateLastModified

            intAge = DateDiff("d", dtmDate, Date)



            If intAge < 90 Then

                i = 1

                Exit For

            End If

        Next



        If i = 0 Then

            Wscript.Echo objSubfolder.Path

        End If

 

        ShowSubFolders objSubfolder

    Next

End Sub

Tak, zdaję sobie z tego sprawę, ten skrypt wygląda na strasznie duży, przynajmniej jak na rubrykę Cześć Skrypciarze. Ale nie panikujcie; w celu ułatwienia jego zrozumienia skopiowałem dużą część kodu. Jak za moment sami zobaczycie, nie jest on ani odrobinę tak przerażający, jak się zdaje. Przykładowo, skrypt zaczyna się w bardzo niestraszny sposób. Zaczynamy od utworzenia wystąpienia obiektu Scripting.FileSystemObject, a następnie stosujemy poniższe dwa wiersze kodu w celu połączenia się z folderem C:\Scripts i pobrania kolekcji wszystkich plików znajdujących się w tym folderze:

Set objStartFolder = objFSO.GetFolder("C:\Scripts")

Set colFiles = objStartFolder.Files
Uwaga. A co z podfolderami folderu C:\Scripts? Nie martwcie się, zaraz do nich dotrzemy.

Po pobraniu kolekcji plików ustawiamy wartość zmiennej licznika i na 0; zastosujemy tę zmienną do śledzenia plików, które zostały zmodyfikowane w ciągu ostatnich 90 dni. Teraz przechodzimy do następującego fragmentu kodu:

For Each objFile in colFiles

    dtmDate = objFile.DateLastModified

    intAge = DateDiff("d", dtmDate, Date)

    If intAge > 90 Then

        i = 1

        Exit For

    End If

Next

Za pomocą tego kodu przechodzimy przez wszystkie pliki znajdujące się w folderze C:\Scripts w celu sprawdzenia, czy znajdują się tam jakieś pliki, które zostały zmodyfikowane w ciągu ostatnich 90 dni. (A co z podfolderami folderu C:\Scripts? Nie martwcie się, zaraz do nich dotrzemy. Obiecuję!) Dla każdego pliku z kolekcji pobieramy wartość właściwości DateLastModified i przypisujemy ją do zmiennej o nazwie dtmDate:

dtmDate = objFile.DateLastModified

W tym momencie używamy funkcji DateDiff skryptu VBScript’s w celu określenia liczby dni ("d"), które upłynęły od daty ostatniego zmodyfikowania pliku (dtmDate) do bieżącej daty (funkcja Date skryptu VBScript). Następnie sprawdzamy, czy ta wartość jest mniejsza niż 90:

If intAge < 90 Then

Załóżmy, że zmienna intAge nie jest mniejsza niż 90, co wskazuje, że plik nie został zmodyfikowany w ciągu ostatnich 90 dni. Co to oznacza? No cóż, to oznacza, że nie udało nam się znaleźć „nowego” pliku w tym folderze; dlatego też wracamy na początek pętli i wykonujemy to samo sprawdzanie dla następnego pliku w naszej kolekcji.

Teraz załóżmy, że intAge jest mniejsza niż 90; to oznacza, że znaleźliśmy nowy plik. Dlatego też robimy teraz dwie rzeczy. Po pierwsze, ustawiamy wartość zmiennej licznika na 1; a następnie wywołujemy instrukcję Exit For w celu opuszczenia pętli For Each.

Uwaga. Dlaczego opuszczamy pętlę? Cóż, pamiętajmy, że szukamy folderów, które nie zawierają żadnych plików zmodyfikowanych w ciągu ostatnich 90 dni. Wystarczyło tylko znaleźć jeden ptaki plik; a skoro już go mamy, nie ma potrzeby kontynuowania działania pętli we wszystkich plikach w folderze.

Naszym następnym krokiem jest określenie, czy zmienna licznika i ma wartość 0. Jeżeli tak jest oznacza to, że dany folder nie zawiera choćby jednego pliku, który został zmieniony w ciągu ostatnich 90 dni. A tego właśnie szukaliśmy, zatem wywołujemy echo ścieżki tego folderu. Do tego służy nam poniższy fragment kodu:

If i = 0 Then

    Wscript.Echo objStartFolder.Path

End If

Tyle, jeżeli chodzi o folder C:\Scripts. A co z podfolderami folderu C:\Scripts?

Bardzo się cieszę, że takie pytanie padło. Kiedy załatwimy już sprawę folderu C:\Scripts, stosujemy następujący wiersz kodu w celu wywołania podprocedura rekursywnej o nazwie ShowSubfolders, przekazując tej podprocedurze ścieżkę do naszego początkowego folderu (C:\Scripts):

ShowSubfolders(objStartFolder)

Nie będę dzisiaj szczegółowo omawiał działania funkcji rekursywnych i podprocedura; to więcej, niż mogę zawrzeć w jednym artykule rubryki Cześć Skrypciarze!. Zwłaszcza w artykule pisanym na dzień przed tygodniową przerwą. więcej informacji na temat rekursywności znajduje się w tej części (j.ang.) przewodnika Microsoft Windows 2000 Scripting Guide.

Tymczasem chciałbym tylko zauważyć, że podprocedura rekursywna to podprocedura, która może sama siebie wywołać. Co to oznacza? Cóż, zauważcie, że pierwszą naszą czynnością w tej podprocedurze jest uruchomienie pętli For Each, która przejdzie przez wszystkie podfoldery wysokiego szczebla w folderze C:\Scripts:

For Each objSubfolder in Folder.SubFolders

Co zrobimy z każdym z tych podfolderów? Dokładnie to samo, co właśnie zrobiliśmy z folderem macierzystym C:\Scripts: sprawdzimy wszystkie pliki i zobaczymy, czy któryś z nich został zmodyfikowany w ciągu ostatnich 90 dni. Przejdziemy przez pierwszy podfolder (np. C:\Scripts\Subfolder1) i sprawdzimy wszystkie pliki. Jeżeli będzie to konieczne, wywołamy echo ścieżki folderu, wskazując, że dany folder nie zawiera ani jednego pliku zmodyfikowanego w ciągu ostatnich 90 dni.

To nam załatwia sprawę podfolderu Subfolder1. Zanim jednak przejdziemy do podfolderu Subfolder2, wykonujemy poniższy wiersz kodu:

ShowSubFolders objSubfolder

Zgadza się: mimo że znajdujemy się już w podprocedurze ShowSubFolders, wywołujemy pordprocedurę ShowSubFolders na nowo. (Dziwne, ale o to chodzi w rekursywności.) To spowoduje, że skrypt powtórzy ten proces z każdym z podfolderów folderu C:\Scripts\Subfolder1, a następnie powtórzy go z każdym z podpodfolderów folderu C:\Scripts\Subfolder1. Dopiero kiedy skończą nam się podfoldery, będziemy mogli wrócić na początek naszej pętli For Each i rozpocząć sprawdzanie folderu C:\Scripts\Subfolder2.

Uwaga. Wiem, ciężko to sobie wyobrazić, nieprawdaż? Na szczęście jednak, nie ma potrzeby rozumienia działania rekursywności i sposobu, w jaki skrypt śledzi jej czynności. VBScript robi to za nas.

 

A to wszystko, co musimy zrobić. Kiedy skrypt skończy działanie, wyświetlona zostanie lista folderów (lub podfolderów), w których żaden z plików nie został zmodyfikowany w ciągu ostatnich 90 dni. A przecież dokładnie o to nam chodziło.

Uwaga. Powinienem jeszcze zauważyć, że ten skrypt może działać wyłącznie na lokalnym komputerze, a to dlatego, że nie było potrzeby, żeby działał na komputerze zdanym. Czy można go zmodyfikować, aby działał na zdalnym komputerze? Niezupełnie. Należałoby go napisać od nowa, wykorzystując usługę WMI, a nie obiekt FileSystemObject. Szczerze mówiąc, nie mam w planach pisania takiego skryptu – trochę to dla mnie kłopotliwe – jeżeli jednak będzie wystarczające zainteresowanie tą kwestią, to się jeszcze raz zastanowię. Dajcie tylko znać.

Na dzisiaj to już wszystko, MM. Nie tylko na dzisiaj, na rok 2007 też. Życzę Wam wszystkim wesołych Świąt i do zobaczenia 2 stycznia 2008 r.

 Do początku strony Do początku strony

Centrum Skryptów - Systemy Operacyjne