How Can I Remove the First Five Lines From All the Log Files in a Folder?

How Can I Remove the First Five Lines From All the Log Files in a Folder?

  • Comments 1
  • Likes
Hey, Scripting Guy! Question

Hey, Scripting Guy! I have about 400 log files in a folder. I need to go in and remove the first 5 lines from each of those log files. How can I write a script to do that?

-- JW

SpacerHey, Scripting Guy! AnswerScript Center

Hey, JW. Before we begin we need to issue a clarification. A few days ago we reported that the Scripting Guy who writes this column had thrown a basketball the length of the court and made a basket; we dutifully termed this the greatest athletic feat in history. As it turns out, we were wrong: what this same Scripting Guy did last night was far more impressive than simply making a full-court shot in basketball.

Interestingly enough, this latest achievement occurred while the Scripting Guy who writes this column was making dinner. The Scripting Stove is none-too-big, which means that, any time you have multiple pots and pans bubbling away, those pots and pans (especially the big ones) sit very close to one another. On top of that, the Scripting Guy who writes this column is none-too-bright; among other things, that means that he has a tendency to leave the handles of these pots and pans pointing out into the middle of the kitchen (as opposed to pointing them away from all the foot traffic).

At any rate, somewhere along the line the Scripting Cook bumped into one of those handles, bumping it with enough force to send it skittering across the stove. Considering the fact that the stove is relatively small, that meant this pot bumped into a second pot, and suddenly both pots – and their contents – were headed off the stove and onto the floor.

At that moment, in a feat worthy of Superman (or, at the very least, Aquaman) the Scripting Guy who writes this column snatched one pot out of mid-air with his left-hand, then somehow managed to grab the handle of the second pot just as it started to slide off the stove. In a split second the problem was solved, and without spilling a drop.

But, really, that was no big deal: all in a day’s work for the Scripting Guy who writes this column.

Speaking of a day’s work, maybe it’s time we put in just that. JW needs a script that can remove the first five lines from every log file in a folder. Can we do that? No problem; it’s as easy as boiling water.

Note. Boiling water is easy. It’s keeping the pot of boiling water from crashing to the floor that’s hard.

Let’s start out by showing you a script that can remove the first five lines from a single text file; we’ll then see if we can figure out how to modify that script so that it works against all the log files in a folder.

Here’s our initial script:

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

As you can see, we start out by defining a pair of constants (ForReading and ForWriting), constants we’ll need when opening the text file. We then use these two lines of code to create an instance of the Scripting.FileSystemObject object and open the file C:\Scripts\Test.txt for reading:

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

Got that? Good. Now, we’re assuming that our text file looks something like this:

1
2
3
4
5
A
B
C
D
E
F
G

As it turns out, the first 5 lines are just header information; we need to delete those 5 lines and leave just the good stuff: ABCDEFG. But how are we going to do that?

We’ll tell you how. (After all, that is our job.) To begin with, we assign the value 1 to a counter variable named i. What are we going to do with this counter variable? You’re about to find out.

After initializing the counter variable we set up a Do Until loop designed to run until we reach the end of the text file (that is, until the file’s AtEndOfStream property is True). Inside that loop, we use the ReadLine method to read the first line in the file, storing that value in a variable named strLine:

strLine = objFile.ReadLine

You know, you’re right: we don’t want the first line in the file, do we? For that matter, we don’t want the next 4 lines, either. Fortunately we’ve already thought of that:

If i > 5 Then

What we’re doing here is checking to see if our counter variable has a value greater than 5; as you might expect, we’re using the counter variable to keep track of which line we just read in from the text file. The first time through the loop we’re reading in line 1; it should come as no surprise, then, that the value of i is also 1.

So what happens if i is less than 5? In that case, we must be dealing with one of the first 5 lines in the text file. We don’t care about those lines so, in essence, we throw them away; we simply increment our counter variable by 1 (making i equal to 2), then loop around and repeat the entire process with line 2 in the text file. Because 2 isn’t greater than 5 we’ll end up ignoring line 2, then loop around and try again with line 3.

Sooner or later we’ll hit line 6; when we do, i will be greater than 5. In that case (and for every subsequent line), we take the value of strLine and assign it to a variable named strContents:

strContents = strContents & strLine & vbCrLf

Actually, that’s only partly true, isn’t it? What we really assign to strContents is the current value of strContents plus the value of strLine plus a carriage return-linefeed (vbCrLf). The net effect? Each time we read in a line from the text file we tack that line onto the end of strContents.

After we’ve read each line we close the file, then immediately reopen it, this time for writing:

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

At this point we call the Write method to write the value of strContents to the file, then close the file for good. What will Test.txt look like now? It’ll look pretty much like it did before, except for one thing: the first 5 lines in the original file won’t be there any more. In other words, Test.txt will now look like this:

A
B
C
D
E
F
G

How ‘bout that?

Of course, that only helps us with the file C:\Scripts\Test.txt; how are we going to perform this same task for all the log files in a folder? Like this, of course:

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

If this looks somewhat similar to the script we just showed you, there’s a good reason for that: it’s pretty much the same script, just tricked out a bit so that it can work against all the log files in C:\Scripts. As you can see, we start out by defining our constants then create an instance of the Scripting.FileSystemObject. After we do that, we connect to the WMI service on the local computer, then use this query to retrieve a collection of all the files in the folder C:\Scripts:

Set colFiles = objWMIService.ExecQuery _
    ("ASSOCIATORS OF {Win32_Directory.Name='C:\Scripts'} Where " _
        & "ResultClass = CIM_DataFile")

What are we going to do with this collection? Well, to begin with, we’re going to set up a For Each loop to walk through each item (that is, each file) in the collection. For each file we’ll then check to see if the Extension is equal to log (without the dot):

If objLogFile.Extension = "log" Then

Note. You might not have to do this. For example, if you want to open all the files in the folder, regardless of file extension, then leave this part of the code out.

If we are dealing with a log file we then assign the file Name (which is equivalent to the file path) to a variable named strFile:

strFile = objLogFile.Name

And now we will use the first script we showed you. The only difference? Instead of hard-coding the file name into our method calls we’ll use the variable strFile to reference the file we want to work with. For example:

Set objFile = objFSO.OpenTextFile(strFile, ForReading)

And guess what? This is going to open the first log file in the folder and remove the first 5 lines from that file. The script will then loop around, open the second log file, and remove the first 5 lines. This will continue until we’ve opened up every log file in C:\Scripts and removed the first 5 lines.

Give it a try and see for yourself.

Before we go we should issue one other clarification. Remember the Scripting Guy who writes this column? Well, as it turns out, his successes might be fewer and farther between then he lets on. Take the kitchen, for example. A more typical cooking session for him would be the one he had a few years ago, when he was making spaghetti. As it will sometimes do, a dab of the spaghetti sauce bubbled up and landed on top of the stove. The Scripting Guy who writes this column dutifully grabbed a dishrag and began wiping up the spilled sauce. As he did so, he apparently drug the dishrag over the burner; a second or two later, he realized that the dishrag he was holding in his hand was on fire.

Which, in case you’re wondering, is not the recommended state for a dishrag.

And then there was the time he dumped noodles into the colander, only then realizing that he hadn’t actually put the colander into the sink yet. And, of course, there was the time that – well, trust us: this could go on forever.

And ever.

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • Scripting Guy, I tried this script, but the results were a little different than I expected. Only the first file the script opened was manipulated correctly. The second file and on were different. First file looked like this;

    a

    b

    c

    d

    e

    Second file looked like this;

    a

    b

    c

    d

    e

    a

    b

    c

    d

    e

    Third file;

    a

    b

    c

    d

    e

    a

    b

    c

    d

    e

    a

    b

    c

    d

    e

    See the difference. Am I doing it wrong somehow? Can you create a fix for this issue?

    Thanks