Centrum Skrypciarzy - Systemy Operacyjne

Jak usunąć pięć pierwszych wierszy ze wszystkich plików dziennika w folderze?

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 usunąć pięć pierwszych wierszy ze wszystkich plików dziennika w folderze?

Cześć Skrypciarze! Pytanie

Cześć, Skrypciarze! Mam około 400 plików dziennika w folderze. Muszę usunąć 5 pierwszych wierszy z każdego z nich. Jak napisać skrypt, który to robi?

-- JW

Cześć Skrypciarze! Odpowiedź

Cześć, JW. Zanim zaczniemy, chcielibyśmy coś sprostować. Kilka dni temu oznajmiliśmy, że Skrypciarz piszący te słowa wrzucił piłkę do kosza przez całe boisko, jednak okazuje się, że nie był to największy sportowy wyczyn w historii. Wczoraj wieczorem zrobił on coś o wiele bardziej imponującego. Stało się to, gdy Skrypciarz przygotowywał kolację. Gdy na kuchence znajdowało się kilka garnków, Skrypciarz piszący te słowa potrącił rączkę jednego z nich, tak, że uderzył on w drugi garnek i oba, wraz z zawartością, zaczęły zlatywać z kuchenki na podłogę. Skrypciarz piszący te słowa dokonał jednak wyczynu godnego Supermana (a przynajmniej Aquamana). Złapał jeden z garnków w powietrzu lewą ręką, a następnie w jakiś sposób złapał rączkę drugiego, gdy ten zaczynał zlatywać z kuchenki. W ułamku sekundy rozwiązał problem bez rozlania ani kropli.

Ale to w zasadzie typowa robota dla Skrypciarza piszącego te słowa. Skoro mowa o robocie, może czas się nią wreszcie zająć. JW potrzebuje skryptu, który usunie pierwsze pięć wierszy z każdego pliku dziennika w folderze. Możemy to zrobić? Żaden problem. To proste jak gotowanie wody.

Uwaga. Gotowanie wody jest proste. Trudne jest sprawienie, żeby garnek z gotującą się wodą nie spadł na podłogę.

Zacznijmy od pokazania wam skryptu, który usuwa pierwsze pięć wierszy z jednego pliku tekstowego. Potem zobaczymy, czy możemy tak go zmodyfikować, aby usuwał je ze wszystkich plików dziennika w folderze.

Oto nasz pierwotny skrypt:

Const ForReading = 1

Const ForWriting = 2



Set objFSo = CreateObject("Scripting.FileSystemObject")

Set objFile = objFSO.OpenTextFile("C:\Scripts\Test.txt", ForReading)



i = 1



Do Until objFile.AtEndOfStream

    strLine = objFile.ReadLine

    If i > 5 Then

        strContents = strContents & strLine & vbCrLf

    End If

    i = i + 1

Loop



objFile.Close



Set objFile = objFSO.OpenTextFile("C:\Scripts\Test.txt", ForWriting)

objFile.Write strContents



objFile.Close

Jak widzicie, zaczynamy od zdefiniowania dwóch stałych, które będą nam potrzebne podczas otwierania pliku tekstowego. Wtedy użyjemy tych dwóch wierszy kodu aby utworzyć wystąpienie obiektu Scripting.FileSystemObject i otworzyć plik C:\Scripts\Test.txt do odczytu:

Set objFSo = CreateObject("Scripting.FileSystemObject")

Set objFile = objFSO.OpenTextFile("C:\Scripts\Test.txt", ForReading)

Łapiecie? Dobrze. Teraz zakładamy, że nasz plik tekstowy wygląda jakoś tak:

1

2

3

4

5

A

B

C

D

E

F

G

Jak się okazuje, pierwsze 5 wierszy to tylko nagłówek. Musimy je usunąć i zostawić najlepsze: ABCDEFG. Ale jak to zrobimy?

Zaraz wam powiemy. (W końcu to nasza praca.) Na początek przydzielimy wartość 1 zmiennej licznika o nazwie i. Co zrobimy z tą zmienną licznika? Zaraz się dowiecie.

Po zainicjowaniu zmiennej licznika, tworzymy pętlę Do Until która będzie działać dopóki nie dotrzemy do końca pliku tekstowego (to znaczy, dopóki wartość własności AtEndOfStream pliku nie wyniesie True). Wewnątrz tej pętli, użyjemy metody ReadLine aby odczytać pierwszy wiersz pliku, przechowując tę wartość w zmiennej o nazwie strLine:

strLine = objFile.ReadLine

Wiecie, macie rację: nie chcemy pierwszego wiersza pliku, prawda? W zasadzie to kolejnych 4 wierszy również. Na szczęście już o tym pomyśleliśmy:

If i > 5 Then

Sprawdzamy tu, czy nasza zmienna licznika ma wartość większą niż 5. Jak można się spodziewać, używamy zmiennej licznika aby sprawdzić, który wiersz właśnie odczytaliśmy z pliku tekstowego. Za pierwszym razem czytamy wiersz 1, nic dziwnego więc, że wartość i również wynosi 1.

Co się stanie, jeśli i wynosi mniej niż 5? W takim wypadku musimy mieć do czynienia z jednym z pierwszych 5 wierszy w pliku, Te wiersze nas nie obchodzą, więc, w skrócie, wyrzucamy je. Po prostu zwiększamy wartość zmiennej licznika o 1 (i jest teraz równe 2) i powtarzamy cały proces z drugim wierszem pliku tekstowego. Jako że 2 nie jest większe niż 5, ostatecznie zignorujemy wiersz 2 i wrócimy, aby spróbować z wierszem 3.

Prędzej czy później dojdziemy do wiersza 6. Gdy tak się stanie, wartość i będzie większa niż 5. W tym wypadku (i dla każego kolejnego wiersza), bierzemy wartość strLine i przydzielamy ją zmiennej o nazwie strContents:

strContents = strContents & strLine & vbCrLf

W zasadzie to tylko częściowo prawda.Tak naprawdę przydzielamy strContents aktualną wartość strContents plus wartość strLine plus znak końca wiersza (vbCrLf). Efekt końcowy? Za każdym razem, gdy odczytujemy wiersz z pliku tekstowego, doklejamy go na koniec strContents.

Po odczytaniu wszystkich wierszy zamykamy plik i natychmiast otwieramy ponownie, tym razem w celu zapisu:

Set objFile = objFSO.OpenTextFile("C:\Scripts\Test.txt", ForWriting)

Używamy teraz metody Write do zapisania wartości strContents do pliku, a następnie zamykamy plik na dobre. Jak będzie teraz wyglądać Test.txt? Mniej więcej tak, jak wcześniej, poza jedną rzeczą: nie będzie tam już pierwszych pięciu wierszy. Innymi słowy, Test.txt wyglądać będzie tak:

A

B

C

D

E

F

G

Jak wam się podoba?

Oczywiście pomaga nam to jedynie w przypadku pliku C:\Scripts\Test.txt. Jak wykonamy to samo zadanie dla wszystkich plików dziennika w folderze? W ten sposób, oczywiście:

Const ForReading = 1

Const ForWriting = 2



Set objFSO = CreateObject("Scripting.FileSystemObject")



strComputer = "."



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



Set colFiles = objWMIService.ExecQuery _

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

        & "ResultClass = CIM_DataFile")



For Each objLogFile In colFiles

    If objLogFile.Extension = "log" Then

        strFile = objLogFile.Name

        Set objFile = objFSO.OpenTextFile(strFile, ForReading)



        i = 1



        Do Until objFile.AtEndOfStream

            strLine = objFile.ReadLine

            If i > 5 Then

                strContents = strContents & strLine & vbCrLf

            End If

            i = i + 1

        Loop



        objFile.Close



        Set objFile = objFSO.OpenTextFile(strFile, ForWriting)

        objFile.Write strContents



        objFile.Close

      End If

Next

Jeśli wygląda to trochę podobnie do poprzedniego skryptu, jest ku temu dobry powód: to w zasadzie ten sam skrypt, tylko trochę przerobiony tak, aby działał na wszystkie pliki dziennika w C:\Scripts. Jak widzicie, zaczynamy od zdefiniowania naszych stałych, po czym tworzymy wystąpienie Scripting.FileSystemObject. Gdy to zrobimy, łączymy się z usługą WMI na lokalnym komputerze, a następnie używamy tej kwerendy do uzyskania kolekcji wszystkich plików w folderze folder C:\Scripts:

Set colFiles = objWMIService.ExecQuery _

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

        & "ResultClass = CIM_DataFile")

Co zrobimy z tą kolekcją? Na początek utworzymy pętlę For Each loop aby przejść przez każdy element (czyli każdy plik) kolekcji. Dla każdego pliku sprawdzimy następnie, czy Extension jest równe log (bez kropki):

If objLogFile.Extension = "log" Then

Uwaga. Możecie nie musieć tego robić. Na przykład, jeśli chcecie otworzyć wszystkie pliki w folderze, bez względu na rozszerzenie plików, usuńcie tę część kodu.

Jeśli plik jest plikiem dziennika, przydzielamy wartość Name (równą ścieżce danego pliku) do zmiennej o nazwie strFile:

strFile = objLogFile.Name

A teraz użyjemy skryptu, który pokazałem wam wcześniej. Jedyna różnica? Zamiast umieszczać nazwę pliku w samym skrypcie użyjemy zmiennej strFile aby określić plik, z którym pracujemy. Na przykład:

Set objFile = objFSO.OpenTextFile(strFile, ForReading)

Zgadnijcie, co się stanie? Te skrypt otworzy pierwszy plik dziennika i usunie pięć pierwszych wierszy. Potem skrypt zapętli się, otworzy drugi plik i usunie pięć pierwszych wierszy. I tak dalej, aż otworzymy wszystkie pliki dziennika w C:\Scripts i usuniemy pięć pierwszych wierszy.

Sami spróbujcie i zobaczcie.

Zanim skończymy, należy coś wyjaśnić. Jak się okazuje, sukcesy Skrypciarza piszącego te słowa nie są aż tak częste. Bardziej typową dla niego sesją kucharską byłaby ta sprzed paru lat, gdy robił spaghetti. Gdy trochę sosu do spaghetti wylądowało na kuchence, Skrypciarz próbował wytrzeć go ścierką. Po paru sekundach zorientował się, że ścierka się pali. Jeśli się zastanawiacie, nie jest to zalecany stan dla ścierki. Kiedyś próbował też wrzucić makaron do cedzaka, po czym zorientował się, że nie włożył jeszcze cedzaka do zlewu. No i oczywiście kiedyś – zaufajcie nam, moglibyśmy tak gadać w nieskończoność.

I dłużej.

 Do początku strony Do początku strony

Centrum Skrypciarzy - Systemy Operacyjne