J'essaie d'utiliser robocopy à l'intérieur de PowerShell pour mettre en miroir certains répertoires sur mes machines personnelles. Voici mon 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"
}
Le script prend un fichier csv avec une liste de répertoires source et de destination. Lorsque j'exécute le script, j'obtiens ces erreurs:
-------------------------------------------------------------------------------
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 !
Une idée de ce que je dois faire pour réparer?
Merci, Mark.
Si les variables de $what
et $options
ne change pas, pourquoi sont-ils des variables?
$what = "/COPYALL /B /SEC /MIR"
$options = "/R:0 /W:0 /NFL /NDL"
Cela fonctionne bien pour moi:
robocopy $source $dest /COPYALL /B /SEC /MIR /R:0 /W:0 /NFL /NDL
Le remplissage des chaînes dans les paramètres des commandes externes à partir de Powershell nécessite un saut de cerceau si vous voulez pouvoir utiliser l'expansion variable et que la ligne de commande résultante comprenne correctement quels paramètres vous souhaitez séparer et lesquels ne devraient pas. Dans votre exemple, vous envoyez la chaîne entière comme premier paramètre et Robocopy vous dit qu'il ne peut pas trouver cette longue chaîne comme répertoire source. Vous voulez que la chaîne Source entière soit traitée comme un paramètre (y compris les espaces qui peuvent s'y trouver), de même pour Destination, mais vos options $ what et $ échoueront car elles seront toutes deux livrées à Robocopy en tant que paramètre unique qui ne peut pas être analysé.
Il existe plusieurs façons de le faire correctement, mais l'extrait de code suivant est basé sur la façon dont vous semblez vouloir décomposer vos paramètres et fonctionne pour l'exemple de répertoire unique que j'ai utilisé.
$source="C:\temp\source"
$dest="C:\temp\dest"
$what = @("/COPYALL","/B","/SEC","/MIR")
$options = @("/R:0","/W:0","/NFL","/NDL")
$cmdArgs = @("$source","$dest",$what,$options)
robocopy @cmdArgs
J'ai eu le même problème. La ligne de commande entière a été interprétée comme le premier argument.
Rien de mentionné ci-dessus n'a fonctionné, y compris:
invoke-expression "robocopy ""$sourceFolder"" ""$destinationFolder"" /MIR"
invoke-expression "robocopy \`"$sourceFolder\`" \`"$destinationFolder\`" /MIR"
Oublier les guillemets ne fonctionne pas lorsqu'il y a un espace sur le chemin:
invoke-expression "robocopy $sourceFolder $destinationFolder /MIR"
Après avoir essayé les astuces http://edgylogic.com/blog/powershell-and-external-commands-done-right/ , je l'ai finalement compris.
robocopy "\`"$sourceFolder"\`" "\`"$destinationFolder"\`" /MIR
Peut-être que j'aurais dû m'en tenir aux fichiers de chauve-souris. :)
Supprimer les guillemets de la ligne robocopy?
c'est à dire.
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
}
J'ai trouvé que la meilleure façon d'exécuter une commande native est d'utiliser la commande & pour exécuter une liste de chaînes. De plus, si vous souhaitez que la sortie de la console soit incluse dans une transcription PowerShell, vous devrez diriger la sortie vers out-Host. Voici un exemple d'appel de 7Zip avec plusieurs paramètres tirés d'un 7-Zip vers Amazon S3 Powershell Script que j'ai écrit:
$7ZipPath = "C:\Program Files\7-Zip\7z.exe" #Path to 7Zip executable
$FolderPath = "C:\Backup" #Folder to backup (no trailing slash!)
$FolderName = $FolderPath.Substring($FolderPath.LastIndexOf("\")+1) #grab the name of the backup folder
$TimeStamp = [datetime]::Now.ToString("yyyy-MM-dd_HHmm") #Create unique timestamp string
$strFile = [String]::Format("{0}\{1}_{2}.7z", "c:\",$FolderName,$TimeStamp) #Create filename for the Zip
#7z options: add, type 7z, Archive filename, Files to add (with wildcard. Change \* to \prefix* or \*.txt to limit files), compression level 9, password, encrypt filenames, Send output to Host so it can be logged.
& $7ZipPath "a" "-t7z" "$strFile" "$FolderPath\*" "-mx9" "-r" "-pPASSWORD" "-mhe" | out-Host #create archive file
if($LASTEXITCODE -ne 0){ #Detect errors from 7Zip. Note: 7z will crash sometimes if file already exists
Write-Error "ERROR: 7Zip terminated with exit code $LASTEXITCODE. Script halted."
exit $LASTEXITCODE
}
Fondamentalement, pour votre cas, j'essaierais quelque chose comme ça (il faudra peut-être détailler les paramètres $ what et $ options individuellement):
$robocopypath = "c:\pathtofolder\robocopy.exe"
& $robocopypath "$source" "$dest" "$what" "$options" "/LOG:MyLogfile.txt"
Cela a fonctionné pour moi et permet une entrée dynamique de l'emplacement du fichier journal. le symbole & indique simplement à PowerShell que le texte est une ligne de code que je veux exécuter.
$source = "E:\BackupToRestore\"
$destination = "E:\RestoreMe\"
$logfile = "E:\robocopyLogFile.txt"
$switches = ("/B", "/MIR", "/XJ", "/FFT", "/R:0", "/LOG:$logfile")
& robocopy $source $destination $roboCopyString $switches
Ajouter mes 2 cents à cela car cela peut aider quelqu'un ... Le code ci-dessous manque la partie "boucle" où je lis un csv pour obtenir les fichiers à copier
# first we setup an array of possible robocopy status
$RobocopyErrors="NO ERRORS",
"OKCOPY",
"XTRA",
"OKCOPY + XTRA",
"MISMATCHES",
"OKCOPY + MISMATCHES",
"MISMATCHES + XTRA",
"OKCOPY + MISMATCHES + XTRA",
"FAIL",
"OKCOPY + FAIL",
"FAIL + XTRA",
"OKCOPY + FAIL + XTRA",
"FAIL + MISMATCHES& goto end",
"OKCOPY + FAIL + MISMATCHES",
"FAIL + MISMATCHES + XTRA",
"OKCOPY + FAIL + MISMATCHES + XTRA",
"***FATAL ERROR***"
#setting some variables with the date
$DateLogFile=get-date -format "yyyyddMMhh"
#this commands below one usually goes into a loop
$DateLog=get-date -format "yyyyddMMhhmmss"
#adding options and command arg as described in previous post
$options = @("/R:0","/W:0")
$cmdArgs = @("$Source","$Destination",$File,$options)
#executing Robocopy command
robocopy @cmdArgs
# We capture the lastexitcode of the command and use to confirm if all was good or not
$errorlevel=$LASTEXITCODE
# I output the status to a log file
"$DateLog`t::$($RobocopyErrors[$errorlevel])::`"$file`"`t`"$Source`" -> `"$Destination`"" | out-file "$scriptPath\Logs\$DateLogFile.log" -append
if ($errorlevel -lt 8) {
#error below 8 = all is good
}
else {
# something bad happened ..
}
invoke-expression "robocopy $source $dest $what $options /LOG:MyLogfile.txt"
Cela interpolera toutes les variables, puis appellera la chaîne résultante. De la façon dont vous l'avez maintenant, il semble que robocopy soit invoqué avec les guillemets autour de toutes les options, c'est-à-dire, robocopy "c:\src c:\dst blah meh". Ceci est interprété comme un seul paramètre.