Centrum Skryptów - Systemy operacyjne

Jak mogę zmienić nazwy plików według daty ich utworzenia? 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 mogę zmienić nazwy plików według daty ich utworzenia?

Cześć Skrypciarzu! Mam w folderze trochę plików dziennika. Chciałbym zmienić nazwy wszystkich plików według nazwy ich utworzenia; na przykład, jeśli plik został utworzony 1 grudnia 2004, chciałbym zmienić jego nazwę na 20041201.log. Czy to możliwe?

-- CK

Cześć CK! Słuchaj, jeśli chodzi o skrypty, to wszystko jest możliwe (oczywiście oprócz tych rzeczy, które nie są możliwe). A ponieważ praca z datami w skryptach WMI może być uciążliwa, w tym konkretnym przypadku format daty WMI ułatwia sprawę.

Aby ułatwić rzecz jeszcze bardziej, podzielmy to zadanie na dwie części. Po pierwsze, potrzebujemy listy wszystkich plików w folderze, wraz z datami ich utworzenia. Jak to zrobić? Na przykład używając takiego skryptu:

strComputer = "."

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



Set FileList = objWMIService.ExecQuery _

    ("ASSOCIATORS OF {Win32_Directory.Name='C:\Logs'} Where " _

        & "ResultClass = CIM_DataFile")



For Each objFile In FileList

    Wscript.Echo objFile.CreationDate

Next

W tym skrypcie łączymy się z usługą WMI, a następnie używamy kwerendy skojarzeniowej, aby uzyskać kolekcję wszystkich plików znajdujących się w folderze C:\Logs. Tytułem wyjaśnienia, jeśli nie wiesz, czym są kwerendy skojarzeniowe, ich działanie jest adekwatne do nazwy: kojarzą ze sobą dwie osobne klasy WMI, w tym wypadku Win32_Directory oraz CIM_DataFile. Dzięki temu możemy uzyskać kolekcję wszystkich plików w skojarzonym folderze.

Kiedy już mamy wszystkie pliki, tworzymy pętlę For Each (dla każdego), a następnie wywołujemy echo właściwości CreationDate (data utworzenia) dla każdego pliku. Ponieważ WMI używa formatu UTC (Universal Time Coordinate - uniwersalna współrzędna czasu), otrzymamy takie wartości:

20041201202723.695209-480

Jasne, że to dziwnie wygląda, ale wiecie co? Tak się składa, że pierwszym 18 znakom odpowiadają rok, miesiąc i dzień, dokładnie te wartości, których chcesz użyć jako nazw plików. Potrzebujesz nazwy 20041201? Spójrz na pierwszych 8 znaków w dacie UTC: 20041201202723.695209-480. Wedle życzenia.

Właściwie aby uzyskać nazwę pliku, musimy tylko użyć funkcji VBScript o nazwie Left (lewy), która uchwyci 8 pierwszych znaków. Ten zmodyfikowany skrypt pobiera te znaki, przechowuje je w zmiennej strDate, a następnie podaje nam echo wartości:

strComputer = "."

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



Set FileList = objWMIService.ExecQuery _

    ("ASSOCIATORS OF {Win32_Directory.Name='c:\Logs'} Where " _

        & "ResultClass = CIM_DataFile")



For Each objFile In FileList

    strDate = Left(objFile.CreationDate, 8)

    Wscript.Echo strDate

Next

To by było na tyle, jeśli chodzi o część pierwszą. Teraz czas na drugi (i ostatni) krok: zmianę nazwy każdego z plików. Najpierw przyjrzyj się skryptowi, a za chwilę wyjaśnimy jego działanie:

strComputer = "."

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



Set FileList = objWMIService.ExecQuery _

    ("ASSOCIATORS OF {Win32_Directory.Name='C:\Logs'} Where " _

        & "ResultClass = CIM_DataFile")



For Each objFile In FileList

    strDate = Left(objFile.CreationDate, 8)

    strNewName = objFile.Drive & objFile.Path & strDate & "." & "log"

    errResult = objFile.Rename(strNewName)

Next

Haczyk tkwi w tworzeniu nowej nazwy pliku. Zmieniając nazwę przy pomocy WMI nie można tak po prostu określić nowej; na przykład, nie można zmienić nazwy Wednesday.log na 20041201.log. Zamiast tego trzeba określić całą ścieżkę i zmienić nazwę pliku C:\Logs\20041201.log. Tym zajmuje się ta linia kodu:

strNewName = objFile.Drive & objFile.Path & strDate & ".log"

Łączymy tu dysk, na którym znajduje się plik (C:), ścieżkę folderu na tym dysku (\Logs\), nową nazwę pliku (20041201, wartość naszej zmiennej strDate) oraz nowe rozszerzenie pliku (.log). Po zestawieniu wszystkiego razem otrzymujemy C:\Logs\20041201.log, czyli kompletną ścieżkę, którą chcemy przypisać do pliku. Teraz wystarczy tylko wywołać metodę Rename (zmień nazwę) i nazwa pliku zostanie zmieniona.

Nawiasem mówiąc, zdajemy sobie sprawę z tego, że konieczność podawania całej ścieżki jest trochę dziwna. Jasna strona tego faktu jest taka, że tym samym sposobem można przenosić pliki do innego folderu. Załóżmy na przykład, że chcesz nie tylko zmienić nazwy plików, ale również przenieść je do folderu C:\Backups. Możesz wówczas użyć takiego skryptu. Zamienia on bieżącą ścieżkę pliku (\Logs\) na nową (\Backups\). Po uruchomieniu skryptu nazwy plików zostaną zmienione, a same pliki przeniesione do folderu C:\Backups:

strComputer = "."

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



Set FileList = objWMIService.ExecQuery _

    ("ASSOCIATORS OF {Win32_Directory.Name='C:\Logs'} Where " _

        & "ResultClass = CIM_DataFile")



For Each objFile In FileList

    strDate = Left(objFile.CreationDate, 8)

    strNewName = objFile.Drive & "\Backups\" &  strDate & ".log"

    errResult = objFile.Rename(strNewName)

Next

Jedyny problem z powyższym skryptem polega na tym, że nie zadziała, jeśli masz dwa pliki z taką samą datą utworzenia; skrypt będzie próbował utworzyć dwa pliki o nazwie, powiedzmy, 20041201.log, a system po prostu bardzo nie lubi dwóch plików o identycznych nazwach w jednym folderze. Jeśli masz taki problem, to poniżej jest przykładowy skrypt, który najpierw sprawdza, czy nazwa pliku jest unikalna, a dopiero potem dokonuje zmian. Załóżmy, że w folderze jest już plik o nazwie 20041201.log. W takim wypadku skrypt (którego działania nie będziemy dziś wyjaśniać w szczegółach) utworzy nową nazwę pliku: 20041201_2.log, a następnie sprawdzi czy taki plik również już istnieje. Jeśli istnieje, skrypt spróbuje nazwy 20041201_3.log i będzie kontynuował, dopóki nie utworzy unikalnej nazwy. Wtedy zmieni nazwę pliku:

strComputer = "."

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



Set FileList = objWMIService.ExecQuery _

    ("ASSOCIATORS OF {Win32_Directory.Name='c:\Logs'} Where " _

        & "ResultClass = CIM_DataFile")



For Each objFile In FileList

    strDate = Left(objFile.CreationDate, 8)

    strNewName = objFile.Drive & objFile.Path & _

       strDate & "." & "log"

    strNameCheck = Replace(strNewName, "\", "\\")



    i = 1

    Do While True

        Set colFiles = objWMIService.ExecQuery _

            ("Select * from Cim_Datafile Where Name = '" & strNameCheck & "'")

        If colFiles.Count = 0 Then

            errResult = objFile.Rename(strNewName)

            Exit Do

        Else

            i = i + 1

            strNewName = objFile.Drive & objFile.Path & _

                strDate & "_" & i & "." & "log"

            strNameCheck = Replace(strNewName, "\", "\\")

        End If

    Loop

Next

Owszem, to trochę skomplikowane, dlatego też dokładniejszą analizę odkładamy na później. Bądź co bądź nie spodziewacie się chyba, że będziemy pracowali nad tą rubryką w nadgodzinach?

 Do początku strony Do początku strony


Centrum Skryptów - Systemy operacyjne