Hello,
I have found a script, that parse the robocopy log file, which looks like this:
-------------------------------------------------------------------------------
ROBOCOPY :: Robust File Copy for Windows
-------------------------------------------------------------------------------
Started : Thu Aug 07 09:30:18 2014
Source : e:\testfolder\
Dest : w:\testfolder\
Files : *.*
Options : *.* /V /NDL /S /E /COPYALL /NP /IS /R:1 /W:5
------------------------------------------------------------------------------
Same 14.6 g e:\testfolder\bigfile - Copy (5).out
Same 14.6 g e:\testfolder\bigfile - Copy.out
Same 14.6 g e:\testfolder\bigfile.out
------------------------------------------------------------------------------
Total Copied Skipped Mismatch FAILED Extras
Dirs : 1 0 1 0
0 0
Files : 3 3 0 0
0 0
Bytes : 43.969 g 43.969 g 0 0 0 0
Times : 0:05:44 0:05:43 0:00:00 0:00:00
Speed : 137258891 Bytes/sec.
Speed : 7854.016 MegaBytes/min.
Ended : Thu Aug 07 09:36:02 2014
Most values at output file are included, but the two speed paramter not.
How can I get this two speed paramters at output file?
Here is the script:
param(
[parameter(Position=0,Mandatory=$true,ValueFromPipeline=$false,HelpMessage='Source Path with no trailing slash')][string]$SourcePath,
[switch]$fp
)
write-host "Robocopy log parser. $(if($fp){"Parsing file entries"} else {"Parsing summaries only, use -fp to parse file entries"})"
#Arguments
# -fp File parse. Counts status flags and oldest file Slower on big files.
$ElapsedTime = [System.Diagnostics.Stopwatch]::StartNew()
$refreshrate=1 # progress counter refreshes this often when parsing files (in seconds)
# These summary fields always appear in this order in a robocopy log
$HeaderParams = @{
"04|Started" = "date";"01|Source" = "string";"02|Dest" = "string";"03|Options" = "string";"07|Dirs" = "counts";"08|Files" = "counts";"09|Bytes" = "counts";"10|Times" = "counts";"05|Ended" = "date";
#"06|Duration" = "string"
}
$ProcessCounts = @{
"Processed" = 0;"Error" = 0;"Incomplete" = 0
}
$tab=[char]9
$files=get-childitem $SourcePath
$writer=new-object System.IO.StreamWriter("$(get-location)\robocopy-$(get-date -format "dd-MM-yyyy_HH-mm-ss").csv")
function Get-Tail([object]$reader, [int]$count = 10) {
$lineCount = 0
[long]$pos = $reader.BaseStream.Length - 1
while($pos -gt 0)
{
$reader.BaseStream.position=$pos
# 0x0D (#13) = CR
# 0x0A (#10) = LF
if ($reader.BaseStream.ReadByte() -eq 10)
{
$lineCount++
if ($lineCount -ge $count) { break }
}
$pos--
}
# tests for file shorter than requested tail
if ($lineCount -lt $count -or $pos -ge $reader.BaseStream.Length - 1) {
$reader.BaseStream.Position=0
} else {
# $reader.BaseStream.Position = $pos+1
}
$lines=@()
while(!$reader.EndOfStream) {
$lines += $reader.ReadLine()
}
return $lines
}
function Get-Top([object]$reader, [int]$count = 10)
{
$lines=@()
$lineCount = 0
$reader.BaseStream.Position=0
while(($linecount -lt $count) -and !$reader.EndOfStream) {
$lineCount++
$lines += $reader.ReadLine()
}
return $lines
}
function RemoveKey ( $name ) {
if ( $name -match "|") {
return $name.split("|")[1]
} else {
return ( $name )
}
}
function GetValue ( $line, $variable ) {
if ($line -like "*$variable*" -and $line -like "* : *" ) {
$result = $line.substring( $line.IndexOf(":")+1 )
return $result
} else {
return $null
}
}
function UnBodgeDate ( $dt ) {
# Fixes RoboCopy botched date-times in format Sat Feb 16 00:16:49 2013
if ( $dt -match ".{3} .{3} \d{2} \d{2}:\d{2}:\d{2} \d{4}" ) {
$dt=$dt.split(" ")
$dt=$dt[2],$dt[1],$dt[4],$dt[3]
$dt -join " "
}
if ( $dt -as [DateTime] ) {
return $dt.ToStr("dd/MM/yyyy hh:mm:ss")
} else {
return $null
}
}
function UnpackParams ($params ) {
# Unpacks file count bloc in the format
# Dirs : 1827 0 1827 0 0 0
# Files : 9791 0 9791 0 0 0
# Bytes : 165.24 m 0 165.24 m 0 0 0
# Times : 1:11:23 0:00:00 0:00:00 1:11:23
# Parameter name already removed
if ( $params.length -ge 58 ) {
$params = $params.ToCharArray()
$result=(0..5)
for ( $i = 0; $i -le 5; $i++ ) {
$result[$i]=$($params[$($i*10 + 1) .. $($i*10 + 9)] -join "").trim()
}
$result=$result -join ","
} else {
$result = ",,,,,"
}
return $result
}
$sourcecount = 0
$targetcount = 1
# Write the header line
$writer.Write("File")
foreach ( $HeaderParam in $HeaderParams.GetEnumerator() | Sort-Object Name ) {
if ( $HeaderParam.value -eq "counts" ) {
$tmp="~ Total,~ Copied,~ Skipped,~ Mismatch,~ Failed,~ Extras"
$tmp=$tmp.replace("~","$(removekey $headerparam.name)")
$writer.write(",$($tmp)")
} else {
$writer.write(",$(removekey $HeaderParam.name)")
}
}
if($fp){
$writer.write(",Scanned,Newest,Summary")
}
$writer.WriteLine()
$filecount=0
# Enumerate the files
foreach ($file in $files) {
$filecount++
write-host "$filecount/$($files.count) $($file.name) ($($file.length) bytes)"
$results=@{}
$Stream = $file.Open([System.IO.FileMode]::Open,
[System.IO.FileAccess]::Read,
[System.IO.FileShare]::ReadWrite)
$reader = New-Object System.IO.StreamReader($Stream)
#$filestream=new-object -typename System.IO.StreamReader -argumentlist $file, $true, [System.IO.FileAccess]::Read
$HeaderFooter = Get-Top $reader 16
if ( $HeaderFooter -match "ROBOCOPY :: Robust File Copy for Windows" ) {
if ( $HeaderFooter -match "Files : " ) {
$HeaderFooter = $HeaderFooter -notmatch "Files : "
}
[long]$ReaderEndHeader=$reader.BaseStream.position
$Footer = Get-Tail $reader 16
$ErrorFooter = $Footer -match "ERROR \d \(0x000000\d\d\) Accessing Source Directory"
if ($ErrorFooter) {
$ProcessCounts["Error"]++
write-host -foregroundcolor red "`t $ErrorFooter"
} elseif ( $footer -match "---------------" ) {
$ProcessCounts["Processed"]++
$i=$Footer.count
while ( !($Footer[$i] -like "*----------------------*") -or $i -lt 1 ) { $i-- }
$Footer=$Footer[$i..$Footer.Count]
$HeaderFooter+=$Footer
} else {
$ProcessCounts["Incomplete"]++
write-host -foregroundcolor yellow "`t Log file $file is missing the footer and may be incomplete"
}
foreach ( $HeaderParam in $headerparams.GetEnumerator() | Sort-Object Name ) {
$name = "$(removekey $HeaderParam.Name)"
$tmp = GetValue $($HeaderFooter -match "$name : ") $name
if ( $tmp -ne "" -and $tmp -ne $null ) {
switch ( $HeaderParam.value ) {"date" { $results[$name]=UnBodgeDate $tmp.trim() }"counts" { $results[$name]=UnpackParams $tmp }"string" { $results[$name] = """$($tmp.trim())""" }
default { $results[$name] = $tmp.trim() }
}
}
}
if ( $fp ) {
write-host "Parsing $($reader.BaseStream.Length) bytes"
# Now go through the file line by line
$reader.BaseStream.Position=0
$filesdone = $false
$linenumber=0
$FileResults=@{}
$newest=[datetime]"1/1/1900"
$linecount++
$firsttick=$elapsedtime.elapsed.TotalSeconds
$tick=$firsttick+$refreshrate
$LastLineLength=1
try {
do {
$line = $reader.ReadLine()
$linenumber++
if (($line -eq "-------------------------------------------------------------------------------" -and $linenumber -gt 16) ) {
# line is end of job
$filesdone=$true
} elseif ($linenumber -gt 16 -and $line -gt "" ) {
$buckets=$line.split($tab)
# this test will pass if the line is a file, fail if a directory
if ( $buckets.count -gt 3 ) {
$status=$buckets[1].trim()
$FileResults["$status"]++
$SizeDateTime=$buckets[3].trim()
if ($sizedatetime.length -gt 19 ) {
$DateTime = $sizedatetime.substring($sizedatetime.length -19)
if ( $DateTime -as [DateTime] ){
$DateTimeValue=[datetime]$DateTime
if ( $DateTimeValue -gt $newest ) { $newest = $DateTimeValue }
}
}
}
}
if ( $elapsedtime.elapsed.TotalSeconds -gt $tick ) {
$line=$line.Trim()
if ( $line.Length -gt 48 ) {
$line="[...]"+$line.substring($line.Length-48)
}
$line="$([char]13)Parsing > $($linenumber) ($(($reader.BaseStream.Position/$reader.BaseStream.length).tostring("P1"))) - $line"
write-host $line.PadRight($LastLineLength) -NoNewLine
$LastLineLength = $line.length
$tick=$tick+$refreshrate
}
} until ($filesdone -or $reader.endofstream)
}
finally {
$reader.Close()
}
$line=$($([string][char]13)).padright($lastlinelength)+$([char]13)
write-host $line -NoNewLine
}
$writer.Write("`"$file`"")
foreach ( $HeaderParam in $HeaderParams.GetEnumerator() | Sort-Object Name ) {
$name = "$(removekey $HeaderParam.Name)"
if ( $results[$name] ) {
$writer.Write(",$($results[$name])")
} else {
if ( $ErrorFooter ) {
#placeholder
} elseif ( $HeaderParam.Value -eq "counts" ) {
$writer.Write(",,,,,,")
} else {
$writer.Write(",")
}
}
}
if ( $ErrorFooter ) {
$tmp = $($ErrorFooter -join "").substring(20)
$tmp=$tmp.substring(0,$tmp.indexof(")")+1)+","+$tmp
$writer.write(",,$tmp")
} elseif ( $fp ) {
$writer.write(",$LineCount,$($newest.ToString('dd/MM/yyyy hh:mm:ss'))")
foreach ( $FileResult in $FileResults.GetEnumerator() ) {
$writer.write(",$($FileResult.Name): $($FileResult.Value);")
}
}
$writer.WriteLine()
} else {
write-host -foregroundcolor darkgray "$($file.name) is not recognised as a RoboCopy log file"
}
}
write-host "$filecount files scanned in $($elapsedtime.elapsed.tostring()), $($ProcessCounts["Processed"]) complete, $($ProcessCounts["Error"]) have errors, $($ProcessCounts["Incomplete"]) incomplete"
write-host "Results written to $($writer.basestream.name)"
$writer.close()
I hope somebody can help me,
Horst
Thanks Horst MOSS 2007 Farm; MOSS 2010 Farm; TFS 2010; TFS 2013; IIS 7.5