Friday, August 9, 2013

PowerShell - Convert PowerShell 'Move-Item' to Robocopy within script.

So you have some code that uses Powershell 'move-item' and insert a line using Robocopy instead.

Q1 - Why would you want to do that?
Well there maybe many reasons. One that came up for me recently was related to network bandwidth. Move-Item was so efficient that it was snagging a little too much network bandwidth and affecting some streaming media performance. One advantage of Robocopy is that it can be throttled more a more gentle effect on the network.

Q2 - What's the big deal?
The issue that many people run into is launching Robocopy with all the parameters when those parameters may contain spaces. The object here is to study and produce code that is immune from these issues.

First of all, lets set up our experiment.

$SrcPath  = "D:\Desktop\Folder With Space"
$FileName = "File With A Space.txt"
$DestPath = "\\SrvName\ShareName\Another Folder With Space"

This works:

Move-Item "$SrcPath\FileName" "$DestPath\$FileName"

The reason this works is because of the quotes.

Tease (1)
So you might think that this would work:

Robocopy "$SrcPath" "$DestPath" "$FileName

It does NOT work because of the spaces in the values of the variables. Of course there are a number of solutions, let me show you the way I like. Firstly we are going to use the PowerShell command Start-Process as it has some nice features like -wait which tell the mother script to wait for the spawned process to complete before continuing. The next part of the approach is to concatenate all the parameters into one variable, and this variable contains the variables you would want to control.

Tease (2)
Conceptually this would look like this:

$Param = "$SrcPath $DestPath $FileName"

Start-Process Robocopy $Param

However that is not going to work, you are going to tie yourself in knots with the spaces that we know could (and in our example do) contain spaces. Ahh! I hear you say, lets just put quotes around it, but if you do that you are going to close the expression, so you will have to more formally concatenate with a + symbol.

Tease (3)
Will this work?

$Param = "$SrcPath" + "$DestPath" + "$FileName"

Start-Process Robocopy $Param

No it doesn't.

OK end of the tease, you need to place the double quotes inside single quotes so that they evaluated correctly and between variables you might as well include the spaces that Robocopy expects between parameters with this little construction:

'" "'

I'm also going to tidy up a little by passing the executable as a variable as well. Here is the finished working code:

$SrcPath  = "D:\Desktop\Folder With Space"
$FileName = "File With A Space.txt"
$DestPath = "\\SrvName\ShareName\Another Folder With Space"
$ExecFile = "Robocopy.exe"
$Param = '"' + $SrcPath + '" "' +$DestPath + '" "' + $FileName + '"'

Start-Process $ExecFile $Param

This will work!


No comments:

Post a Comment