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