Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Function Initialize-RobocopyJob {
- <#
- .SYNOPSIS
- Executes Robocopy to recursively copy a specified directory to any location.
- .DESCRIPTION
- Launches Robocopy.exe (assumed to be included with the OS) with parameters supplied via arguments or optionally in batch mode reading data from a CSV or XLSX file.
- Current default options are to recursively copy data while preserving security ACLs, Ownership, and Timestamps information.
- Log files are created in a LOGS directory at the current path of execution. If the LOGS directory does not exist it will be created.
- .PARAMETER JobName
- Optional field used in naming the transcript and copy job log files.
- .PARAMETER SrcPath
- The path of the folder to be copied as a string. Be sure to enclose in double quotes if the path contains a space in it.
- .PARAMETER DestPath
- The destination path the files should be copied to. If the -MIR switch is included then files in the destination path which are not in the source will be purged.
- .PARAMETER DirExclusions
- Partial or full folder names to be excluded. (see the Robocopy docs for the /XD parameter.)
- Multiple entries should be passed in the form of an array. e.g. -DirExclusions ('Dir1','Dir2')
- .PARAMETER FileExclusions
- Partial or full file names to be excluded. (see the Robocopy docs for the /XF parameter.)
- Multiple entries should be passed in the form of an array. e.g. -FileExclusions ('desktop.ini','*.exe')
- .PARAMETER MIR
- Optional switch specifying that Robocopy should be run the /MIR parameter which purges files from the destination that are not found in the source.
- See Robocopy docs on /MIR for more info. If not specified /E is ued instead which copies all subdirectories (including empty ones) but does not purge.
- .PARAMETER DataMap
- Instead of specifying -SrcPath and -DestPath you can provide the path to a CSV or XLSX file which will be parsed.
- Each row of the datamap sheet will be a separate robocopy job. They will be run serially (not simultaneously) and will share a common transcript
- log but have distinct Robocopy Job logs. The CSV or XLSX must contain the following headers as the first row of the file:
- SourcePath, DestinationPath, DirExclusions, FileExclusions
- SourcePath and DestinationPath must be filled out. Any lines missing one of those will be ignored.
- .PARAMETER MonitorCopy
- Optional switch that when specified will spawn a new PowerShell window which tails the Robocopy job log.
- Nice for monitoring long jobs. Closing the spawned windows will not affect the job itself. The windows do not auto-close on job completion.
- .PARAMETER NoTranscript
- Optional parameter which disables the transcript logging. Robocopy job logs are still created for each job.
- .NOTES
- Name: Initialize-RoboCopyJob
- Author: mOjO_mOjO
- Version History:
- 1.0 - Ported this over from another script.
- .EXAMPLE
- Initialize-RobocopyJob -JobName Dir1Copy -SrcPath "C:\Dir1" -DestPath "\\SERVER\SHARE\Dir1"
- Initiates a job to copy "Dir1".
- .EXAMPLE
- Initialize-RobocopyJob -JobName "Dir1Copy" -SrcPath "C:\Dir1" -DestPath "\\SERVER\SHARE\Dir1" -MIR -FileExclusions ('*.lnk','desktop.ini') -MonitorCopy
- Initiates the same copy job but excluding .lnk files and files named "desktop.ini". Also uses the mirror option which purges any files from the destination
- which are not in the source.
- #>
- [cmdletBinding(SupportsShouldProcess,ConfirmImpact="High")]
- Param(
- [String]$JobName,
- [string][Alias('Path','SourcePath')]$SrcPath,
- [string][Alias('Destination','DestinationPath')]$DestPath,
- [array][Alias('XD')]$DirExclusions= @(),
- [array][Alias('XF')]$FileExclusions= @(),
- [switch][Alias('Mirror')]$MIR,
- [string]$DataMap,
- [switch]$MonitorCopy,
- [string]$LogDir = $($pwd.Path + "\LOGS"),
- [switch]$NoTranscript
- )
- $StartTime = Get-Date
- $DateString = (get-date -UFormat %Y%m%d%H%M)
- If (!$(Test-Path -PathType Container -Path $LogDir)) { New-Item -ItemType Directory -path $LogDir }
- If (!$(Test-Path -PathType Container -Path $LogDir)) { Write-Host "Invalid log directory or unable to create $($LogDir). Exiting." -f Red; Return "ERROR" }
- If ($JobName) {
- $LogPath = $LogDir + "\RoboCopy_" + $DateString + "_" + $($JobName | Remove-InvalidFileNameChars) + "_Log.txt"
- } else {
- $LogPath = $LogDir + "\RoboCopy_" + $DateString + "_Log.txt"
- }
- If (!$NoTranscript) {
- try { stop-transcript | out-null } catch {}
- start-transcript -Path $LogPath
- }
- [array]$DataMigrationMap = @()
- if ($DataMap) {
- $DataMapObj = Get-Item $DataMap -ErrorAction SilentlyContinue
- If (!$DataMapObj) { Write-Host "`nInvalid or missing data mapping file specified. Check the path and try again." -f Red; try {Stop-Transcript} catch {}; Return "ERROR"}
- If ($DataMapObj.Extension -notmatch '.csv|.xlsx') { Write-Host "`nInvalid mapping file type specified. Must be .xlsx or .csv file." -f Red; try {Stop-Transcript} catch {}; Return "ERROR"}
- If ($Matches[0] -eq '.xlsx') {
- $DataMigrationMap = Import-Excel -Path $DataMapObj.FullName
- $DataMigrationMap = $DataMigrationMap | ?{$_.SourcePath -and $_.DestinationPath}
- If (!$DataMigrationMap) { Write-Host "No valid data found in datamap file. Headers must be `"SourcePath`", `"DestinationPath`", and optional `"Exclusions`"" -f Red; try {Stop-Transcript} catch {}; Return "ERROR" }
- } elseif ($Matches[0] -eq '.csv') {
- $DataMigrationMap = Import-CSV -Path $DataMapObj.FullName
- $DataMigrationMap = $DataMigrationMap | ?{$_.SourcePath -and $_.DestinationPath}
- If (!$DataMigrationMap) { Write-Host "No valid data found in datamap file. Headers must be `"SourcePath`", `"DestinationPath`", and optional `"Exclusions`"" -f Red; try {Stop-Transcript} catch {}; Return "ERROR" }
- }
- } elseif ($SrcPath -and $DestPath) {
- [array]$DataMigrationMap = [PSCustomObject]@{
- SourcePath = $SrcPath
- DestinationPath = $DestPath
- DirExclusions = [array]$DirExclusions
- FileExclusions = [array]$FileExclusions
- }
- }
- if ($DataMigrationMap) {
- ForEach ($Entry in $DataMigrationMap) {
- $EntryNum = "{0:00}" -f $($DataMigrationMap.IndexOf($Entry) + 1)
- If ($JobName) {
- $CopyLog = $LogDir + "\RoboCopy_" + $DateString + "_" + $($JobName | Remove-InvalidFileNameChars) + "_" + $EntryNum + "_JobLog.txt"
- } else {
- $CopyLog = $LogDir + "\RoboCopy_" + $DateString + "_" + $EntryNum + "_JobLog.txt"
- }
- $FullSrcPath = $Entry.SourcePath
- $FullDestPath = $Entry.DestinationPath
- [string]$exclSTR = $null
- If ($Entry.DirExclusions) {
- $exclSTR += $Entry.DirExclusions | %{ "/XD " + '"' + $_ + '"' }
- }
- If ($Entry.FileExclusions) {
- $exclSTR += $Entry.FileExclusions | %{ "/XF " + '"' + $_ + '"' }
- }
- If (!(Test-Path $FullSrcPath)) { Write-Host "`nInvalid source path specified." -f Red; if (!$NoTranscript) { try {Stop-Transcript} catch {} }; Return "ERROR"}
- If (!(Test-Path $FullDestPath)) {
- [array]$DestPathArr = $FullDestPath.Split('\')
- If ($DestPathArr.Count -gt 1) {
- If (Test-Path $($DestPathArr[0..$($DestPathArr.Count - 2)] -join("\"))) {
- Write-Warning "Destination path $($FullDestPath) does not exist. It will be created."
- } else { Write-Host "`nInvalid destination path specified." -f Red; if (!$NoTranscript) { try {Stop-Transcript} catch {} }; Return "ERROR" }
- }
- }
- # Write-Host "`tStart Time: $(Get-Date)"
- $RoboCopyCore = "robocopy `"$($FullSrcPath)`" `"$($FullDestPath)`" /LOG:`"$($CopyLog)`""
- $RoboCopyArgs = "/R:0 /W:0 /COPY:DATSO /DCOPY:DAT /MT /NP"
- If ($MIR) { $RoboCopyArgs = $RoboCopyArgs + " /MIR" } else { $RoboCopyArgs = $RoboCopyArgs + " /E" }
- If ($exclSTR) { $RoboCopyArgs = $RoboCopyArgs + " " + $($exclSTR) }
- $RoboCopyCMD = $RoboCopyCore + " " + $RoboCopyArgs
- Write-Verbose "Robocopy Command: $($RoboCopyCMD)"
- write-host "`nStarting Robocopy Entry `#$($EntryNum)"
- write-host "`tSource:`t`t$($FullSrcPath)"
- write-host "`tDestination:`t$($FullDestPath)"
- If ($Entry.DirExclusions) { write-host "`tDirExclusions: $($Entry.DirExclusions -Join(', '))" -f Yellow }
- If ($Entry.FileExclusions) { write-host "`tFileExclusions: $($Entry.FileExclusions -Join(', '))" -f Yellow }
- write-host "`tRobocopy Args:`t$($RoboCopyArgs)"
- Write-Host
- if ($pscmdlet.ShouldProcess("Robocopy entry `#$($EntryNum)")) {
- if ($MonitorCopy) {
- Write-Host "`tOpening copy job log file for monitoring in a new window:`n`t`t$($CopyLog)" -f Cyan
- Write-Host "`tNote: Closing the monitoring windows will not affect the copy jobs.`n" -f Yellow
- $ArgList = "-command `"start-sleep 1; Get-Content -Wait `"$($CopyLog)`"`""
- Start-Process -FilePath "PowerShell.exe" -ArgumentList $ArgList
- } else {
- Write-Host "`nRobocopy job is running. To monitor the copy job paste the below command into a new powershell window:" -f Cyan
- write-host "`t`tGet-Content -Wait `"$($CopyLog)`"`n" -F Magenta
- }
- write-verbose "Executing $($RoboCopyCMD)"
- $a = Invoke-Expression $RoboCopyCMD
- $CopyLogResultsHead = Get-Content -Head 30 -Path $CopyLog
- Write-Host "`tRoboCopy Header:"
- for ($i = 5; ($($CopyLogResultsHead[$i]) -notmatch "----------") -and $i -lt 30; $i++) { write "`t$($CopyLogResultsHead[$i])" }
- # Write-Host "`tEnd Time: $(Get-Date)"
- Write-Host "`tRoboCopy Results:"
- $CopyLogResultsTail = Get-Content -Tail 16 -Path $CopyLog
- for ($i = 0; $i -lt $CopyLogResultsTail.Count; $i++) { if ( $CopyLogResultsTail[$i] -match "----------") { [int]$iStart = $i + 2 } }
- if (!$iStart) { $iStart = 0 }
- for ($i = $iStart; $i -lt $CopyLogResultsTail.Count; $i++) { Write "`t$($CopyLogResultsTail[$i])" }
- }
- } # End ForEach Loop
- } else {
- write-host "No valid DataMigrationMap entries found. Data migration will be skipped." -F Red; if (!$NoTranscript) { try {Stop-Transcript} catch {} }; Return "ERROR"
- }
- write-Host "`nAll jobs complete @ $(Get-Date). Total time elapsed: $($StartTime - (get-date))"
- if (!$NoTranscript) { try {Stop-Transcript} catch {} }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement