none
Robocopy Scripting RRS feed

  • Question

  • Hi guys,

    Am new to power shell scripting, Copied bits of code and made a script but want to include functionality to show failed failed files to my existing code

    Please help

    # Define the backup location
    $destination = "D:\CODs"
    
    #$computername = gc env:computername
    
    if(!(test-path "$destination\$env:username + \ "))
    {
      new-item "$destination\$env:username" -ItemType Directory
    
        if(!(test-path "$destination\$env:username"))
        {
          new-item "$destination\$env:username"   -ItemType Directory
    
          #new-item "$destination\$env:username\AppData\Local\Microsoft\Outlook"   -ItemType Directory
          new-item "$destination\$env:username\Desktop"                           -ItemType Directory
          new-item "$destination\$env:username\Downloads"                         -ItemType Directory
          new-item "$destination\$env:username\Favorites"                         -ItemType Directory
          new-item "$destination\$env:username\Documents"                         -ItemType Directory
         # new-item "$destination\$env:username\Cookies"                           -ItemType Directory
          new-item "$destination\$env:username\Pictures"                           -ItemType Directory
    
    }}
    
    
    
    Robocopy.exe "$env:userprofile\Desktop"                                        "$destination\$env:username\desktop"                           /tee /log:"$destination\$env:username\desktop.txt"    /XX /MIR /XA:SH /XD /XJD /R:1 /W:1 /MT:32 /V /NP /XF *.mp3 *.mp4      *.ost   *.iso *.avi   *.lnk /ETA  /NJH 
    Robocopy.exe "$env:userprofile\Downloads"                                      "$destination\$env:username\Downloads"                         /tee /log:"$destination\$env:username\Downloads.txt"   /XX /MIR  /XA:SH /XD /XJD /R:1 /W:1 /MT:32 /V /NP /XF *.mp3 *.mp4     *.ost   *.iso    *.avi *.lnk /ETA /NJH
    Robocopy.exe "$env:userprofile\Favorites"                                      "$destination\$env:username\Favorites"                          /tee /log:"$destination\$env:username\Favorites.txt"    /XX /MIR  /XA:SH /XD /XJD /R:1 /W:1 /MT:32 /V /NP /XF *.mp3 *.mp4   *.ost   *.iso   *.avi *.lnk /ETA /NJH
    Robocopy.exe "$env:userprofile\Documents"                                      "$destination\$env:username\Documents"                           /tee /log:"$destination\$env:username\Documents.txt"  /XX /MIR  /XA:SH /XD /XJD /R:1 /W:1 /MT:32 /V /NP /XF *.mp3 *.mp4   *.ost   *.iso   *.avi *.lnk /ETA /NJH
    #Robocopy.exe "$env:userprofile\cookies"                                        "$destination\$env:username\cookies"                             /tee /log:"$destination\$env:username\cookies.txt"    /XX /MIR /XA:SH /XD /XJD /R:1 /W:1 /MT:32 /V /NP /XF *.mp3 *.mp4   *.ost   *.iso   *.avi *.lnk /ETA /NJH
    Robocopy.exe "$env:userprofile\Pictures"                                       "$destination\$env:username\Pictures"                             /tee /log:"$destination\$env:username\Pictures.txt"   /XX /MIR /XA:SH /XD /XJD /R:1 /W:1 /MT:32 /V /NP /XF *.mp3 *.mp4  *.ost   *.iso  *.avi  *.lnk /ETA /NJH
    #Robocopy.exe "$destination\$env:username\AppData\Local\Microsoft\Outlook"      "$destination\$env:username\AppData\Local\Microsoft\Outlook"      /tee /log:"$destination\$env:username\AppData\Local\Microsoft\Outlook.txt"   /XA:SH /XD /XJD /R:1 /W:1 /MT:32 /V /NP /XF *.mp3 *.mp4*.ost *.iso *.avi *.lnk /ETA NJH
    
    <#
    # The following attempts to get the error code for Robocopy
    # and use this as extra infromation and email determination.
    # NO OTHER CODE BETWEEN THE SWITCH AND THE ROBOCOPY COMMAND
    
    
    Switch ($LASTEXITCODE)
    {
    16
    {
    $exit_code = "16"
    $exit_reason = "***FATAL ERROR***"
    #$IncludeAdmin = $False
    #$SendEmail = $False
    }
    8
    {
    $exit_code = "8"
    $exit_reason = "**FAILED COPIES**"
    #$IncludeAdmin = $False
    #$SendEmail = $False
    }
    4
    {
    $exit_code = "4"
    $exit_reason = "*MISMATCHES*"
    $IncludeAdmin = $False
    #$SendEmail = $False
    }
    2
    {
    $exit_code = "2"
    $exit_reason = "EXTRA FILES"
    $IncludeAdmin = $False
    #$SendEmail = $False
    }
    1
    {
    $exit_code = "1"
    $exit_reason = "Copy Successful"
    $IncludeAdmin = $False
    $SendEmail = $False
    }
    0
    {
    $exit_code = "0"
    $exit_reason = "No Change-All Files in Sync "
    $SendEmail = $False
    $IncludeAdmin = $False
    }
    default
    {
    $exit_code = "Unknown ($LASTEXITCODE)"
    $exit_reason = "Unknown Reason"
    #$SendEmail = $False
    $IncludeAdmin = $False
    }
    }
    
    # Modify the subject with Exit Reason and Exit Code
    $Subject += " : " + "Code_No: "+ $exit_code + " " +" EC: " + $exit_reason + ""
    
    # Test log file size to determine if it should be emailed
    # or just a status email
    If ((Get-ChildItem $Filelog).Length -lt 30mb)
    {
    If ($IncludeAdmin)
    {
    If ($AsAttachment)
    {
    Send-MailMessage -From $Sender -To $Recipients -Cc $Admin -Subject $Subject -Body " $env:username Backup results are attached." -Attachment $Filelog -DeliveryNotificationOption onFailure -SmtpServer $SMTPServer
    } Else {
    Send-MailMessage -From $Sender -To $Recipients -Cc $Admin -Subject $Subject -Body (Get-Content $LogFile  | Out-String) -DeliveryNotificationOption onFailure -SmtpServer $SMTPServer
                                                                                       
    }
    } Else {
    If ($AsAttachment)
    {
    Send-MailMessage -From $Sender -To $Recipients -Subject $Subject -Body " $env:username Backup results are attached." -Attachment $Filelog  -DeliveryNotificationOption onFailure -SmtpServer $SMTPServer
    } Else {
    Send-MailMessage -From $Sender -To $Recipients -Subject $Subject -Body (Get-Content $Filelog | Out-String) -DeliveryNotificationOption onFailure -SmtpServer $SMTPServer
    }
    }
    } Else {
    # Creat the email body from the beginning and end of the $Logfile
    $Body = "Logfile was too large to send." + (Get-Content $Filelog -TotalCount 15 | Out-String) + (Get-Content $Filelog | Out-String)
    # Include Admin if log file was too large to email
    Send-MailMessage -From $Sender -To $Recipients -Cc $Admin -Subject $Subject -Body $Body -DeliveryNotificationOption onFailure -SmtpServer $SMTPServer
    #Exclude Admin if log file was too large to email
    #Send-MailMessage -From $Sender -To $Recipients -Subject $Subject -Body $Body -DeliveryNotificationOption onFailure -SmtpServer $SMTPServer
    }
    #>
    ##### Combine all  Log files a single Fine
    $Logfile = "$destination\$env:username\Pictures.txt"
    $Logfile1 = "$destination\$env:username\Documents.txt"
    $Logfile2 = "$destination\$env:username\Favorites.txt"
    $Logfile3 = "$destination\$env:username\desktop.txt"
    $Logfile4 = "$destination\$env:username\Downloads.txt"
    #$Logfile5 = "$destination\$env:username\cookies.txt"
    #$Logfile6 = "$destination\$env:username\AppData\Local\Microsoft\Outlook.txt"
    
    $Filelog = "$destination\$env:username\log.txt" 
    
    Get-Content $Logfile,$Logfile1,$Logfile2,$Logfile3,$Logfile4 | Out-File -filepath "$destination\$env:username\log.txt" |Out-String
    
    #$Logfile5,
    #$Logfile6
    
    #Email
    ##################################################################
    
    $Subject = "Backup_$env:username Results: BackUp  Job- Local To Remote"
    $SMTPServer = "10.100.176.110"
    $Sender = "andrew.kasaija@spedaginterfreight.com"
    $Recipients = "andrew.kasaija@spedaginterfreight.com"
    $Admin = " "
    $SendEmail = $True
    $IncludeAdmin = $False
    $AsAttachment = $True
    
    
    ###########################################################
    
    #Need to Include this Code
    
    #Requires -Version 4
    
    function Log {
    <# 
     .Synopsis
      Function to log input string to file and display it to screen
    
     .Description
      Function to log input string to file and display it to screen. Log entries in the log file are time stamped. Function allows for displaying text to screen in different colors.
    
     .Parameter String
      The string to be displayed to the screen and saved to the log file
    
     .Parameter Color
      The color in which to display the input string on the screen
      Default is White
      Valid options are
        Black
        Blue
        Cyan
        DarkBlue
        DarkCyan
        DarkGray
        DarkGreen
        DarkMagenta
        DarkRed
        DarkYellow
        Gray
        Green
        Magenta
        Red
        White
        Yellow
    
     .Parameter LogFile
      Path to the file where the input string should be saved.
      Example: c:\log.txt
      If absent, the input string will be displayed to the screen only and not saved to log file
    
     .Example
      Log -String "Hello World" -Color Yellow -LogFile c:\log.txt
      This example displays the "Hello World" string to the console in yellow, and adds it as a new line to the file c:\log.txt
      If c:\log.txt does not exist it will be created.
      Log entries in the log file are time stamped. Sample output:
        2014.08.06 06:52:17 AM: Hello World
    
     .Example
      Log "$((Get-Location).Path)" Cyan
      This example displays current path in Cyan, and does not log the displayed text to log file.
    
     .Example 
      "$((Get-Process | select -First 1).name) process ID is $((Get-Process | select -First 1).id)" | log -color DarkYellow
      Sample output of this example:
        "MDM process ID is 4492" in dark yellow
    
     .Example
      log "Found",(Get-ChildItem -Path .\ -File).Count,"files in folder",(Get-Item .\).FullName Green,Yellow,Green,Cyan .\mylog.txt
      Sample output will look like:
        Found 520 files in folder D:\Sandbox - and will have the listed foreground colors
    
     .Link
      https://superwidgets.wordpress.com/category/powershell/
    
     .Notes
      Function by Sam Boutros
      v1.0 - 08/06/2014
      v1.1 - 12/01/2014 - added multi-color display in the same line
    
    #>
    
        [CmdletBinding(SupportsShouldProcess=$true,ConfirmImpact='Low')] 
        Param(
            [Parameter(Mandatory=$true,
                       ValueFromPipeLine=$true,
                       ValueFromPipeLineByPropertyName=$true,
                       Position=0)]
                [String[]]$String, 
            [Parameter(Mandatory=$false,
                       Position=1)]
                [ValidateSet("Black","Blue","Cyan","DarkBlue","DarkCyan","DarkGray","DarkGreen","DarkMagenta","DarkRed","DarkYellow","Gray","Green","Magenta","Red","White","Yellow")]
                [String[]]$Color = "Green", 
            [Parameter(Mandatory=$false,
                       Position=2)]
                [String]$LogFile,
            [Parameter(Mandatory=$false,
                       Position=3)]
                [Switch]$NoNewLine
        )
    
        if ($String.Count -gt 1) {
            $i=0
            foreach ($item in $String) {
                if ($Color[$i]) { $col = $Color[$i] } else { $col = "White" }
                Write-Host "$item " -ForegroundColor $col -NoNewline
                $i++
            }
            if (-not ($NoNewLine)) { Write-Host " " }
        } else { 
            if ($NoNewLine) { Write-Host $String -ForegroundColor $Color[0] -NoNewline }
                else { Write-Host $String -ForegroundColor $Color[0] }
        }
    
        if ($Filelog.Length -gt 2) {
            "$(Get-Date -format "yyyy.MM.dd hh:mm:ss tt"): $($String -join " ")" | Out-File -Filepath $Filelog_New -Append 
        } else {
            Write-Verbose "Log: Missing -LogFile parameter. Will not save input string to log file.."
        }
    }
    
    function Get-FailedFiles {
    <# 
     .SYNOPSIS
      Script to parse Robocopy log file(s) and return files that failed to copy.
    
     .DESCRIPTION
      This script will parse Robocopy log file(s) and return a PS object that has 2 properties: FilePath and ErrorCode fro each file that failed to copy.
    
     .PARAMETER RoboLog
      Path to Robocopy log file
    
     .PARAMETER FailedFilesCSV
      Path to the output file that lists the files that failed to copy along with their error codes.
    
     .PARAMETER CopystatsCSV
      Path to the output file that lists summaries of files and folders copied/failed and copy duration.
    
     .PARAMETER Sum
      Optional switch that adds a line at the end of the CopyStatsCSV tallying all prior lines.
    
     .EXAMPLE
      Get-FailedFiles -RoboLog .\logs\Robo-Migrate-FileShares_NYFILSRV01P-2015-03-11_05-27-26AM.txt
      The script will return list of files that failed to copy and the corresponding error codes (in decimal)
    
     .EXAMPLE
      $FailedFiles = Get-FailedFiles (Get-ChildItem -Path .\logs | where { $_.Name.StartsWith('Robo') }).FullName
      This command will parse all the files under .\logs subfolder that start with 'Robo' and return the files that
      failed to copy and their error codes. This can be presented:
      $FailedFiles | FT -Auto                             # in tabular format
      $FailedFiles | Out-Gridview                         # in Powershell ISE Gridview
      $FailedFiles | Export-Csv .\FailedFiles.CSV -NoType # or exported to CSV
    
     .OUTPUTS 
      This function returns a PS object that has 2 properties: FilePath and ErrorCode.
    
     .LINK
      https://superwidgets.wordpress.com/category/powershell/
    
     .NOTES
      Function by Sam Boutros
      v1.0 - 03/11/2015
      v1.1 - 03/17/2015 - Added functionality to gather file and folder copy summaries and export to CSV
    
    #>
    	
    	[CmdletBinding()]
    	Param (
    		[Parameter(Mandatory = $true, Position = 0)]
    		    [ValidateScript({Test-Path -Path $_})][String[]]$Filelog_New,
    		[Parameter(Mandatory = $false, Position = 1)]
                [String]$FailedFilesCSV = "$PSScriptRoot\FailedFiles-$(Get-Date -format yyyy-MM-dd_hh-mm-sstt).CSV",
    		[Parameter(Mandatory = $false, Position = 2)]
                [String]$CopyStatsCSV = "$PSScriptRoot\CopyStats-$(Get-Date -format yyyy-MM-dd_hh-mm-sstt).CSV",
            [Parameter(Mandatory = $false, Position = 3)] 
                [Switch]$Sum = $true
    	)
    	
        $FailedFiles = @()
        foreach ($Filelog in $Filelog_New) {
            log 'Processing file',$LogFile,'...' Green,Cyan -NoNewLine
            $LogLines = Get-Content $LogFile
            log $LogLines.Count,'lines loaded' Cyan,Green
    
            log 'Detecting files that failed to copy, compiling list... ' -NoNewLine
            $LogLines -match ' ERROR ' -match 'Copying File' | % {
                $Props = [ordered]@{
                    FilePath  = $_.Substring($_.IndexOf('Copying File') + 12 , $_.Length - $_.IndexOf('Copying File') - 12).Trim()
                    ErrorCode = $_.Substring($_.IndexOf(' ERROR ')+7,2).Trim()
                }
                $FailedFiles += New-Object -TypeName PSObject -Property $Props
            }
            log 'detected',$Failedfiles.Count,'files that failed to copy' Green,Yellow,Green
    
            log 'Compiling file/folder copy statistics..' -NoNewLine
            $CopyStats = @()
            $LogLines | % {
                if ($_ -match '   Source : ') { $Source      = $_.Substring(12,$_.Length - 12 ) }
                if ($_ -match '     Dest : ') { $Destination = $_.Substring(12,$_.Length - 12 ) }
                if ($_ -match '    Dirs :')   { 
                    $DirTotal   = [Long]$_.Substring(12,10).Trim() 
                    $DirCopied  = [Long]$_.Substring(22,10).Trim() 
                    $DirFailed  = [Long]$_.Substring(52,10).Trim() 
                }
                if ($_ -match '   Files : ' -and $_.Length -gt 60) { 
                    $FileTotal  = [Long]$_.Substring(12,10).Trim() 
                    $FileCopied = [Long]$_.Substring(22,10).Trim() 
                    $FileFailed = [Long]$_.Substring(52,10).Trim() 
                }
                if ($_ -match '   Times :')  { $Duration  = [TimeSpan]$_.Substring(12,10).Trim() }
                if ($_ -match '   Speed : ') { $Speed = $_.Substring(12,$_.Length - 12 ).Trim() }
                if ($_ -match '   Ended : ') { 
                    $Ended = $_.Substring(11,$_.Length - 11 ).Trim() 
                    $Props = [ordered]@{
                        Source         = $Source
                        Destination    = $Destination
                        DirTotal       = $DirTotal
                        NewDirCopied   = $DirCopied
                        DirFailed      = $DirFailed
                        Filetotal      = $FileTotal
                        NewFileCopied  = $FileCopied
                        FileFailed     = $FileFailed
                        Duration       = $Duration
                        Speed          = $Speed
                        Ended          = $Ended
                    }
                    $CopyStats += New-Object -TypeName PSObject -Property $Props
                }    
            } # foreach $LogLines
            if ($Sum) {
                $Props = [ordered]@{
                    Source         = 'Total'
                    Destination    = ''
                    DirTotal       = ($CopyStats | Measure-Object -Property DirTotal -Sum).Sum    
                    NewDirCopied   = ($CopyStats | Measure-Object -Property NewDirCopied -Sum).Sum 
                    DirFailed      = ($CopyStats | Measure-Object -Property DirFailed -Sum).Sum 
                    Filetotal      = ($CopyStats | Measure-Object -Property Filetotal -Sum).Sum 
                    NewFileCopied  = ($CopyStats | Measure-Object -Property NewFileCopied -Sum).Sum 
                    FileFailed     = ($CopyStats | Measure-Object -Property FileFailed -Sum).Sum 
                    Duration       = ''
                    Speed          = ''
                    Ended          = ''
                }
                $CopyStats += New-Object -TypeName PSObject -Property $Props
            }
            log 'done'
            log ($CopyStats | FT -Auto | Out-String)
    
        } # foreach $LogFile
    
        $FailedFiles | Export-Csv $FailedFilesCSV -NoType
        $CopyStats   | Export-Csv $CopyStatsCSV -NoType
    
    } 


    Monday, September 24, 2018 8:35 AM

Answers

All replies