Як змусити робокопію працювати в панцирі?


24

Я намагаюся використовувати роботокопію всередині shellhell, щоб відобразити деякі каталоги на своїх домашніх машинах. Ось мій сценарій:

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"
}

Сценарій містить файл CSV із переліком джерел та каталогів призначення. Коли я запускаю сценарій, я отримую ці помилки:

-------------------------------------------------------------------------------
   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 !

Будь-яка ідея, що мені потрібно зробити, щоб виправити?

Спасибі, Марку.

Відповіді:


10

Якщо змінні для $whatі $optionsне змінюються, чому вони змінні?

$what = "/COPYALL /B /SEC /MIR" 
$options = "/R:0 /W:0 /NFL /NDL" 

Це добре для мене:

robocopy   $source $dest /COPYALL /B /SEC /MIR /R:0 /W:0 /NFL /NDL

Хороший момент - нехай це буде просто. :)
Helvick

3
також / сек не / сек / тут є критичним

1
Отже, ви просто пропустили / Журнал, і він спрацював :-) У вас є те, що у вас виникають дивні помилки, що викликають роботокопію з PS, коли Logfile заздалегідь не існує.
icnivad

6
Я знаю, що це стара публікація, але я думаю, що варто сказати, що наявність цих змінних є сигналом для майбутніх читачів сценарію, що вони повинні були бути налаштованими частинами сценарію. Причина цього працює в тому, що трапляється виправити друкарську помилку в оригіналі $ what.
Восьминіг

2
Навіть якщо щось не змінюється, змінна інкапсуляція може допомогти зробити сценарій менш закрученим. І якщо виявиться, що мені потрібно згодом знову посилатися на цю змінну, це робить сценарій більш динамічним
Колоб Каньйон

20

Для заселення рядків у параметри для зовнішніх команд з Powershell потрібні певні стрибки обруча, якщо ви хочете використовувати змінне розширення, а також отриманий командний рядок правильно зрозуміти, які параметри ви хочете розділити, а які не слід. У вашому прикладі ви надсилаєте весь рядок як перший параметр, і Robocopy повідомляє вам, що він не може знайти цю довгу рядок як вихідний каталог. Ви хочете, щоб весь рядок Source трактувався як один парам (включаючи пробіли, які можуть бути там), також для Destination, але ваші параметри $ what і $ не будуть працювати, оскільки вони будуть доставлені в Robocopy як єдиний параметр, який не може бути розібраний

Існує кілька способів зробити це правильно, але наступний фрагмент базується на тому, як ви, здається, хочете розбити свої параметри та працює для прикладу єдиного каталогу, який я використав.

$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

Дякую за відповідь. Я спробував ваш код, але все одно я отримую таку помилку: ПОМИЛКА: Неправильний параметр №3: "/ COPYALL / B / SEC / MIR"
Марк Еллісон

Коли я запускаю вищезазначений код заглушки (скопійований зверху), він працює точно так, як очікувалося - конкретно всі параметри \ які елементи визнаються окремими параметрами. Якщо ви запускаєте лише вказану вище заглушку (із папкою-джерелом, яка існує), чи працює вона? Якщо так, то двічі перевірте котирування \ ухилення у власному модифікованому коді. Недійсний параметр №3 вказує на те, що ваша версія $ що досі є однією строкою, а не масив окремих параметрів у коді, який ви виконуєте.
Гельвік

2
+1. Оце, безумовно, тут питання. Мені здається смішним, як люди постійно намагаються використовувати PowerShell так, ніби це була стара тексту, що базується лише на тексті ;-)
Joey

@Joey Ви знайшли об'єктну модель силового корпусу на практиці краще, ніж текстові?
Дідьє А.

1
@DidierA. Однозначно. Особливо там , де об'єкти існують , щоб описати речі , з якими ви спілкуєтеся, наприклад , файли, процеси, послуги і т.д. Але навіть якщо у вас є тільки вбудовані додатки та строкові виходів ви можете просто використовувати звичайні рядкові оператори, наприклад , -matchі -replaceтак само , як фільтрація / проекційні командлети працювати з цим. Звичайно, це досить добре розроблено в цьому плані (більшість *-Objectкоманд є ортогональними, і всі вони можуть бути застосовані до будь-якого об'єкта).
Joey

3

Видалити лапки з лінії роботокопії?

тобто

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
}

Ні, я спробував це спочатку, і це не спрацювало (подібні помилки), тому я змінив його на те, що показано вище. Будь-які інші ідеї?
Марк Еллісон

Який вихід, коли ви запускаєте його без лапок? Ваш оригінальний вихід із зображенням Джерела як "P: \ C: \ Резервне копіювання \ Фото \ COPYALL \ B \ SEC \ \ MIR \ R: 0 \ W: 0 \ NFL \ NDL \ LOG: MyLogfile.txt \" було те, що було моїм увага до цитат.
Брайан

3

У мене була така ж проблема. Весь командний рядок трактувався як перший аргумент.

Ніщо згадане вище не працювало, включаючи:

invoke-expression "robocopy ""$sourceFolder"" ""$destinationFolder"" /MIR"  
invoke-expression "robocopy \`"$sourceFolder\`" \`"$destinationFolder\`" /MIR"  

Якщо випустити цитати, це не працює, якщо на шляху є пробіл:

invoke-expression "robocopy $sourceFolder $destinationFolder /MIR"  

Спробувавши хитрощі в http://edgylogic.com/blog/powershell-and-external-commands-done-right/ , я нарешті це зрозумів.

robocopy "\`"$sourceFolder"\`" "\`"$destinationFolder"\`" /MIR

Можливо, я мав би застрягти з файлами bat. :)


Чи перейшло ваше посилання на edgylogic на slai.github.io/posts/… ?
Генрік Стаун Поульсен

1

Я виявив, що найкращим способом виконання нативної команди є використання команди & виконувати список рядків. Крім того, якщо ви хочете, щоб вихід консолі був включений у розшифровку силових оболонок, вам потрібно буде передати висновок на вихідний хост. Ось приклад виклику 7Zip з декількома параметрами, взяті з 7-Zip до сценарію Amazon S3 Powershell, який я написав:

$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
}

В основному для вашого випадку я б спробував щось подібне (можливо, знадобиться окреслити параметри $ what і $ options окремо):

$robocopypath = "c:\pathtofolder\robocopy.exe"
& $robocopypath "$source" "$dest" "$what" "$options" "/LOG:MyLogfile.txt"

Проблема в цьому полягає в тому, що, як ви говорите, "$ what" і "$ options" будуть відправлені в роботокопію як окремі параметри, а не список окремих, і зважаючи на його зразок коду, їх доведеться розбивати, не може бути це.
Helvick

Ви можете використовувати оператор splat, @якщо ви використовуєте powershell v3 для розділення списку, розділеного комами, в аргумент стека
Zasz

0
invoke-expression "robocopy $source $dest $what $options /LOG:MyLogfile.txt"

Це дозволить інтерполювати всі змінні, а потім викликати отриманий рядок. Як у вас це зараз, схоже, на роботокопію посилаються цитати навколо всіх варіантів, тобто роботокопія "c: \ src c: \ dst blah meh". Це трактується як єдиний параметр.


0

Це працювало для мене і дозволяє динамічно вводити розташування файлу журналу. символ & просто повідомляє PowerShell, що текст - це рядок коду, який я хочу запустити.

    $source = "E:\BackupToRestore\"
    $destination = "E:\RestoreMe\"
    $logfile = "E:\robocopyLogFile.txt"    
    $switches = ("/B", "/MIR", "/XJ", "/FFT", "/R:0", "/LOG:$logfile")
    & robocopy $source $destination $roboCopyString $switches

0

Додавання до цього моїх 2 копійок, оскільки це може допомогти комусь ... У наведеному нижче коді відсутня частина "циклу", де я читаю csv, щоб отримати файли для копіювання

# 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 ..  

}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.