08/27/2012

Dividing Log File by MAC Addresses

Using powrshell regex and array indices to divide appended log entries to separate files

We use a network PXE booting environment to wipe the hard drives of all end of life equipment using a third party disk sanitation utility. The wipe software typically generates a log file for every machine wiped on the network and stores it on a share. The naming convention of the log is based on the MAC address of the on-board ethernet interface appended by -del. An example would be 00:11:22:33:44:55-del.txt. The problem is with certain model laptops the program detects the wireless interface before the ethernet interface but reports the wireless nic's MAC address as "unavailable". Since the logging method uses the first interface mac to name the file the resulting log is created with a generic name and all subsequent logs for the same laptop model are appended to one file called "unavailable-del.txt" instead of being logged individually. With hundreds of appended entries this meant many hours of tedious copy and paste operations to create the separate log files we need for each machine. Unfortunately the wipe software vendor was not able to help in a timely manner. Knowing a few things about powershell I set out to script a solution.

First let's take a look a look at an example of Unavailable-del.txt (Note: The make, model, manufacturer, serial numbers, and mac addresses have been altered in the example log file.) At the top of the log's contents are the headers followed by the appended wipe entries. All fields are tilde delimited. Let's start by setting a few variables and creating our regex to extract the ethernet interface mac addresses as the values to name our new files with.

$logName = "C:\users\name\desktop\test\Unavailable-del.txt"
$path = Split-Path $logname -Parent; $path += "\"
Set-Location $path

[regex]$regex="\w\w:\w\w:\w\w:\w\w:\w\w:\w\w"
$log = (gc ".\Unavailable-del.txt")

I just want to take a moment to point out the "Split-Path" cmdlet because I didn't know about it at first and was using an overly complicated method of obtaining the parent path of the file I chose to run the script on. Let's compare the two methods.

Before learning about the Split-Path cmdlet:

$logName = "C:\users\name\desktop\test\Unavailable-del.txt"
$i = ($logName.Split("\").Length) -2
$path = $logName.Split("\")[0..$i] -join "\"

After learning about the Split-Path cmdlet:

$logName = "C:\users\name\desktop\test\Unavailable-del.txt"
$logName = Split-Path $logName -Parent

It's clear the latter example is much more efficient. Having already stored the contents of Unavailable-del.txt in the variable $log using $log = (gc .\Unavailable-del.txt)we now need to set up a counter usering a For statement to run through each index of $log followed by a Foreach loop to run a series of commands on each index of $log.

for ( $i = 0; $i -lt $log.Length; $i++ ) {
    foreach ( $record in $log[$i] ) {
        $record -match $regex
        $mac = $matches[0] + "-del.txt"
        $mac = $mac -replace ":","-"
        $newName = $path + $mac
        $log[0] + "`r`n" + $record | Out-File $newName
    }
}

So foreach index of $log we are using the regex to identify the mac address and storing it in the variable $mac. Then we concatenate the string "-del.txt" in keeping with our desired naming convention. $mac = $mac -replace ":","-" replaces all instances of ":" in the filename since this character is not allowed in a filename on a windows file system. Next we join the variable $path containing the parent path of Unavailable-del.txt and $mac containing the new file-name. $mac now looks like "00-11-22-33-44-55-del.txt". Finally we concatenate $log[0] containing the header info of Unavailable-del.txt, again the content of which is stored in $log, insert a carriage return (for windows) and newline (nix) followed by $record which contains the entire log entry for mac address we are working with. Then use the powershell pipeline to output the contents of those variables to $newName ("C:\users\name\desktop\test\00-11-22-33-44-55-del.txt"). These steps will be performed for every mac address entry in Unavailable-del.txt.

Here is the original log file:

Before running the script After running the script

Example of one of the resulting logs:

The full script:

$logName = "C:\users\name\desktop\test\Unavailable-del.txt"
$path = Split-Path $logname -Parent; $path += "\"
Set-Location $path

[regex]$regex="\w\w:\w\w:\w\w:\w\w:\w\w:\w\w"
$log = (gc .\Unavailable-del.txt)

for ( $i = 0; $i -lt $log.Length; $i++ ) {
    foreach ( $record in $log[$i] ) {
        $record -match $regex
        $mac = $matches[0] + "-del.txt"
        $mac = $mac -replace ":","-"
        $newName = $path + $mac
        $log[0] + "`r`n" + $record | Out-File $newName
    }
}

Top

HTML Comment Box is loading comments...