I'm trying to use robocopy inside powershell to mirror some directories on my home machines. Here's my script:
param ($configFile)
$config = Import-Csv $configFile
$what = "/COPYALL /B /SEC/ /MIR"
$options = "/R:0 /W:0 /NFL /NDL"
$logDir = "C:\Backup\"
foreach ($line in $config)
{
$source = $($line.SourceFolder)
$dest = $($line.DestFolder)
$logfile = $logDIr
$logfile += Split-Path $dest -Leaf
$logfile += ".log"
robocopy "$source $dest $what $options /LOG:MyLogfile.txt"
}
The script takes in a csv file with a list of source and destination directories. When I run the script I get these errors:
-------------------------------------------------------------------------------
ROBOCOPY :: Robust File Copy for Windows
-------------------------------------------------------------------------------
Started : Sat Apr 03 21:26:57 2010
Source : P:\ C:\Backup\Photos \COPYALL \B \SEC\ \MIR \R:0 \W:0 \NFL \NDL \LOG:MyLogfile.txt\
Dest -
Files : *.*
Options : *.* /COPY:DAT /R:1000000 /W:30
------------------------------------------------------------------------------
ERROR : No Destination Directory Specified.
Simple Usage :: ROBOCOPY source destination /MIR
source :: Source Directory (drive:\path or \\server\share\path).
destination :: Destination Dir (drive:\path or \\server\share\path).
/MIR :: Mirror a complete directory tree.
For more usage information run ROBOCOPY /?
**** /MIR can DELETE files as well as copy them !
Any idea what I need to do to fix?
Thanks, Mark.
Populating strings into parameters for external commands from within Powershell requires some hoop jumping if you want to be able to use variable expansion and also have the resulting command line properly understand which parameters you want to be separated and which should not. In your example you are sending the entire string as the first parameter and Robocopy is telling you that it can't find that long string as a source directory. You do want the entire Source string to be treated as one param (including spaces that may be in there), likewise for Destination but your $what and $options will fail because they will both be delivered to Robocopy as a single parameter which cannot be parsed.
There are a few ways to do this right but the following snippet is based on the way you seem to want to break out your parameters and does work for the single directory example I've used.
If the variables for
$what
and$options
don't change, why are they variables?This works fine for me:
Remove the quotes from the robocopy line?
i.e.
I had the same problem. The whole command line was interpreted as the first argument.
Nothing mentioned above worked including:
Leaving out the quotes doesn't work when there's a space in the path:
After trying the tricks in http://edgylogic.com/blog/powershell-and-external-commands-done-right/, I finally got it.
Maybe I should have stuck with bat files. :)
I have found that the best way to execute a native command is to use the & command to execute a list of strings. Also if you want the console output to be included in a powershell transcript you will need to pipe the output to out-host. Here is an example of calling 7Zip with multiple parameters taken from a 7-Zip to Amazon S3 Powershell Script that I wrote:
Basically for your case I would try something like this (may need to break out the $what and $options parameters individually):
This worked for me and allows for a dynamic input of the log file location. the & symbol just tells PowerShell that the text is a line of code I want to run.
Adding my 2 cents to this as it may help someone... The below code is missing the "loop" part where I read a csv to get the files to copy
This will interpolate all of the variables, then call the resulting string. The way you have it now, it looks like robocopy is being invoked with the quotes around all of the options, i.e., robocopy "c:\src c:\dst blah meh". This is interpreted as a single parameter.