PowerShell: Copy and Move Files Using Robocopy and CSV

This script will read from a CSV file and get Source, (Copy/Move) Destination and Description.

CSV Filename:  <ScriptName>_SrcDst.csv
CSV Header Layout:  Source,CopyDestination,MoveDestination,Description

 

It will do the following:

  1. Copy files from Source to CopyDestination.
  2. Move files from Source to MoveDestination.
  3. Write to a Log File to a Logs folder (creates it if it doesn’t exist)
  4. Log file is named the same as the script filename, with the date and time appended to the end
  5. Uses the Description from the CSV to separate Copy/Move log entries.

 

As there are some differences between what Windows Server 2003 and Windows Server 2016 can do… <groans>

I have written two slightly different scripts that will work on their respective version of powershell.

 

PowerShell v3 and Up

[CmdletBinding()]
Param
(
	[string]$SrcDstFile = "$PSScriptRoot\$(([system.io.fileinfo]$MyInvocation.MyCommand.Definition).BaseName)_SrcDst.csv",
	[string]$RobocopyPath = 'c:\Windows\system32\robocopy.exe',
	[string]$IncludeFile = '*.*',
	[string]$RoboCOPYParameters = '/COPY:DAT /NP /NDL /FP /XX /R:1 /W:2 /XF *.db',
	[string]$RoboMOVEParameters = '/MOV /NP /NDL /FP /R:1 /W:2 /XF *.db',
	[string]$LogFileName = "$PSScriptRoot\Logs\$(([system.io.fileinfo]$MyInvocation.MyCommand.Definition).BaseName)-log_$(Get-Date -Format 'yyyyMMdd').txt",
	[switch]$Tee = $false
)


Begin
{
	# Turn on verbose
	$VerbosePreference = 'Continue'

	# Begin Logging
	Add-Content -Value "**** Job Started: $(([system.io.fileinfo]$MyInvocation.MyCommand.Definition).BaseName) Copy and Move files script at $(Get-Date -Format 'yyyyMMdd_HHmm') ****" -Path $LogFileName

	$RoboCOPYParameters = "$RoboCOPYParameters /LOG+:$LogFileName"
	if ($Tee) {$RoboCOPYParameters = "$RoboCOPYParameters /TEE"}

	$RoboMOVEParameters = "$RoboMOVEParameters /LOG+:$LogFileName"
	if ($Tee) {$RoboMOVEParameters = "$RoboMOVEParameters /TEE"}
	
	Write-Verbose "RoboCOPY Parameters: $RoboCOPYParameters"
	Write-Verbose "RoboMOVE Parameters: $RoboMOVEParameters"
}
Process
{
	# Building the robocopy command line
	Import-CSV "$($SrcDstFile)" | foreach {
		Write-Verbose "Beginning COPY for: $($_.Description) at $(Get-Date -Format 'yyyyMMdd_HHmmss')"
		Add-Content "Beginning COPY for: $($_.Description) at $(Get-Date -Format 'yyyyMMdd_HHmmss')" -Path $LogFileName
		$RoboCOPYExecute = "$($RobocopyPath) `"$($_.Source)`" `"$($_.CopyDestination)`" $($IncludeFile) $($RoboCopyParameters)"
		Invoke-Expression $RoboCOPYExecute
		Write-Verbose "Completed COPY for: $($_.Description) at $(Get-Date -Format 'yyyyMMdd_HHmmss')"
		Add-Content "Completed COPY for: $($_.Description) at $(Get-Date -Format 'yyyyMMdd_HHmmss')" -Path $LogFileName
		}

	Import-CSV "$($SrcDstFile)" | foreach {
		Write-Verbose "Beginning MOVE for: $($_.Description) at $(Get-Date -Format 'yyyyMMdd_HHmmss')"
		Add-Content "Beginning MOVE for: $($_.Description) at $(Get-Date -Format 'yyyyMMdd_HHmmss')" -Path $LogFileName
		$RoboMOVEExecute = "$($RobocopyPath) `"$($_.Source)`" `"$($_.MoveDestination)`" $($IncludeFile) $($RoboMOVEParameters)"
		Invoke-Expression $RoboMOVEExecute
		Write-Verbose "Completed MOVE for: $($_.Description) at $(Get-Date -Format 'yyyyMMdd_HHmmss')"
		Add-Content "Completed MOVE for: $($_.Description) at $(Get-Date -Format 'yyyyMMdd_HHmmss')" -Path $LogFileName
		}
	}
End
{
	Add-Content -Value "**** Job Ended: $(([system.io.fileinfo]$MyInvocation.MyCommand.Definition).BaseName) Copy and Move files script at $(Get-Date -Format 'yyyyMMdd_HHmm')" -Path $LogFileName
}

 

 

PowerShell v2 (Works on Windows Server 2003)

[CmdletBinding()]
Param
(
	[String]$PSScriptRoot = (Split-Path $MyInvocation.MyCommand.Path),
	[string]$SrcDstFile = "$PSScriptRoot\$(([system.io.fileinfo]$MyInvocation.MyCommand.Definition).BaseName)_SrcDst.csv",
	[string]$RobocopyPath = 'c:\Windows\system32\robocopy.exe',
	[string]$IncludeFile = '*.*',
	[string]$RoboCOPYParameters = '/COPY:DAT /NP /NDL /FP /XX /R:1 /W:2 /XF *.db',
	[string]$RoboMOVEParameters = '/MOV /NP /NDL /FP /R:1 /W:2 /XF *.db',
	[string]$LogFileName = "$PSScriptRoot\Logs\$(([system.io.fileinfo]$MyInvocation.MyCommand.Definition).BaseName)-log_$(Get-Date -Format 'yyyyMMdd').txt",
	[switch]$Tee = $false
)
write-host $PSSCriptRoot


# Turn on verbose
$VerbosePreference = 'Continue'

# Begin Logging
Add-Content -Value "**** Job Started: $(([system.io.fileinfo]$MyInvocation.MyCommand.Definition).BaseName) Copy and Move files script at $(Get-Date -Format 'yyyyMMdd_HHmm') ****" -Path $LogFileName

$RoboCOPYParameters = "$RoboCOPYParameters /LOG+:$LogFileName"
if ($Tee) {$RoboCOPYParameters = "$RoboCOPYParameters /TEE"}

$RoboMOVEParameters = "$RoboMOVEParameters /LOG+:$LogFileName"
if ($Tee) {$RoboMOVEParameters = "$RoboMOVEParameters /TEE"}

Write-Verbose "RoboCOPY Parameters: $RoboCOPYParameters"
Write-Verbose "RoboMOVE Parameters: $RoboMOVEParameters"


# Building the robocopy command line
Import-CSV "$($SrcDstFile)" | foreach {
	Write-Verbose "Beginning COPY for: $($_.Description) at $(Get-Date -Format 'yyyyMMdd_HHmmss')"
	Add-Content "Beginning COPY for: $($_.Description) at $(Get-Date -Format 'yyyyMMdd_HHmmss')" -Path $LogFileName
	$RoboCOPYExecute = "$($RobocopyPath) `"$($_.Source)`" `"$($_.CopyDestination)`" $($IncludeFile) $($RoboCopyParameters)"
	Invoke-Expression $RoboCOPYExecute
	Write-Verbose "Completed COPY for: $($_.Description) at $(Get-Date -Format 'yyyyMMdd_HHmmss')"
	Add-Content "Completed COPY for: $($_.Description) at $(Get-Date -Format 'yyyyMMdd_HHmmss')" -Path $LogFileName
}

Import-CSV "$($SrcDstFile)" | foreach {
	Write-Verbose "Beginning MOVE for: $($_.Description) at $(Get-Date -Format 'yyyyMMdd_HHmmss')"
	Add-Content "Beginning MOVE for: $($_.Description) at $(Get-Date -Format 'yyyyMMdd_HHmmss')" -Path $LogFileName
	$RoboMOVEExecute = "$($RobocopyPath) `"$($_.Source)`" `"$($_.MoveDestination)`" $($IncludeFile) $($RoboMOVEParameters)"
	Invoke-Expression $RoboMOVEExecute
	Write-Verbose "Completed MOVE for: $($_.Description) at $(Get-Date -Format 'yyyyMMdd_HHmmss')"
	Add-Content "Completed MOVE for: $($_.Description) at $(Get-Date -Format 'yyyyMMdd_HHmmss')" -Path $LogFileName
}

Add-Content -Value "**** Job Ended: $(([system.io.fileinfo]$MyInvocation.MyCommand.Definition).BaseName) Copy and Move files script at $(Get-Date -Format 'yyyyMMdd_HHmm')" -Path $LogFileName

 

That’s it folks, enjoy!