วิธีที่จะทำให้ robocopy ทำงานใน powershell?


24

ฉันกำลังพยายามใช้ robocopy ภายใน powershell เพื่อทำมิเรอร์บางไดเร็กทอรีบนเครื่องที่บ้านของฉัน นี่คือสคริปต์ของฉัน:

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
ดังนั้นคุณเพียงแค่ข้าม / Log และใช้งานได้ :-) Gotcha ก็คือคุณได้รับข้อผิดพลาดแปลก ๆ ที่เรียก Robocopy ด้วย PS เมื่อ Logfile ไม่มีอยู่ก่อน
icnivad

6
ฉันรู้ว่านี่เป็นโพสต์เก่า แต่ฉันคิดว่ามันคุ้มค่าที่จะบอกว่าการใช้ตัวแปรเหล่านี้เป็นสัญญาณบ่งบอกถึงผู้อ่านในอนาคตของสคริปต์ว่าสิ่งเหล่านี้มีความหมายว่าเป็นส่วนที่กำหนดค่าได้ของสคริปต์ เหตุผลที่การทำงานนี้เกิดขึ้นเพื่อแก้ไขการพิมพ์ผิดในสิ่งที่ $ เดิม
Octopus

2
แม้ว่าบางสิ่งจะไม่เปลี่ยนแปลง แต่การห่อหุ้มตัวแปรสามารถช่วยทำให้สคริปต์มีความซับซ้อนน้อยลง และถ้าปรากฎว่าฉันต้องการอ้างอิงตัวแปรนั้นอีกครั้งในภายหลังมันจะทำให้สคริปต์มีชีวิตชีวามากขึ้น
Kolob Canyon

20

การเติมสตริงลงในพารามิเตอร์สำหรับคำสั่งภายนอกจากภายใน Powershell ต้องมีการกระโดดแบบวนซ้ำหากคุณต้องการใช้การขยายตัวของตัวแปรและยังมีบรรทัดคำสั่งที่เป็นผลลัพธ์เข้าใจอย่างถูกต้องว่าพารามิเตอร์ใดที่คุณต้องการแยกออก ในตัวอย่างของคุณคุณกำลังส่งสตริงทั้งหมดเป็นพารามิเตอร์แรกและ Robocopy กำลังบอกคุณว่าไม่พบสตริงที่ยาวเป็นไดเรกทอรีต้นทาง คุณต้องการให้สตริงต้นทางทั้งหมดถูกถือว่าเป็นหนึ่งพารามิเตอร์ (รวมถึงช่องว่างที่อาจมี) เช่นเดียวกันสำหรับปลายทาง แต่ตัวเลือก $ 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"
Mark Allison

เมื่อฉันเรียกใช้รหัส stub ด้านบน (คัดลอกมาจากด้านบน) มันทำงานได้ตามที่คาดไว้ - โดยเฉพาะตัวเลือกทั้งหมด \ รายการที่ได้รับการยอมรับเป็นพารามิเตอร์แยก หากคุณเรียกใช้เฉพาะต้นขั้วด้านบน (มีโฟลเดอร์ต้นทางที่มีอยู่) ใช้งานได้หรือไม่ ถ้าเป็นเช่นนั้นให้ตรวจสอบ Quotes \ escaping ในรหัสที่แก้ไขของคุณเอง พารามิเตอร์ที่ไม่ถูกต้อง # 3 บ่งชี้ว่าเวอร์ชันของ $ คืออะไรยังคงเป็นสตริงเดี่ยวไม่ใช่อาร์เรย์ของพารามิเตอร์แยกต่างหากในรหัสที่คุณกำลังเรียกใช้
Helvick

2
+1 นั่นเป็นปัญหาที่นี่แน่นอน ฉันคิดว่ามันตลกดีที่ผู้คนพยายามใช้ PowerShell อย่างต่อเนื่องราวกับว่าเป็นเชลล์แบบข้อความอย่างเดียว ;-)
Joey

@ โจอี้คุณคิดว่าแบบจำลองวัตถุของพาวเวอร์เชลทำงานได้ดีกว่าแบบฝึกที่ใช้ข้อความหรือไม่?
Didier A.

1
@DidierA: แน่นอน โดยเฉพาะอย่างยิ่งที่วัตถุมีอยู่เพื่ออธิบายสิ่งที่คุณโต้ตอบเช่นไฟล์กระบวนการบริการ ฯลฯ แต่แม้ว่าคุณจะมีแอปพลิเคชั่นดั้งเดิมและเอาต์พุตสตริงคุณก็สามารถใช้ตัวดำเนินการสตริงปกติเช่น-matchและ-replaceกรอง / ฉาย cmdlet ทำงานกับมัน โดยทั่วไปแล้วค่อนข้างออกแบบมาอย่างดีในเรื่องนั้น ( *-Objectคำสั่งส่วนใหญ่เป็นฉากและพวกเขาทั้งหมดสามารถนำไปใช้กับวัตถุใด ๆ )
Joey

3

ลบคำพูดจากสาย robocopy หรือไม่

กล่าวคือ

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
}

ไม่ฉันลองครั้งแรกแล้วและมันไม่ทำงาน (ข้อผิดพลาดที่คล้ายกัน) ดังนั้นฉันจึงเปลี่ยนเป็นสิ่งที่แสดงด้านบน ความคิดอื่น ๆ ?
Mark Allison

เอาต์พุตเมื่อคุณรันโดยไม่มีเครื่องหมายคำพูดคืออะไร ผลลัพธ์ดั้งเดิมของคุณแสดงที่มาเป็น "P: \ C: \ Backup \ Photos \ 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

บางทีฉันควรจะติดกับไฟล์ค้างคาว :)


ลิงก์ของคุณไปยัง edgylogic ถูกย้ายไปที่slai.github.io/posts/… ?
Henrik Staun Poulsen

1

ฉันพบว่าวิธีที่ดีที่สุดในการรันคำสั่งเนทีฟคือการใช้คำสั่ง & เพื่อรันรายการสตริง นอกจากนี้หากคุณต้องการให้รวมเอาท์พุทคอนโซลในทรานสคริปต์ PowerShell คุณจะต้องไพพ์เอาต์พุตไปยังโฮสต์ภายนอก นี่คือตัวอย่างของการเรียก 7Zip ด้วยพารามิเตอร์หลายตัวที่นำมาจาก7-Zip ถึง Amazon S3 Powershell Scriptที่ฉันเขียน:

$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" จะถูกส่งไป robocopy เป็นพารามิเตอร์เดียวแทนที่จะเป็นรายการของแยกและให้รหัสตัวอย่างของพวกเขาพวกเขาจะต้องแตกออกไม่มีอาจเกี่ยวกับ มัน.
Helvick

คุณสามารถใช้ตัวดำเนินการ splat @หากคุณใช้ powershell v3 เพื่อแยกรายการที่คั่นด้วยเครื่องหมายจุลภาคเป็นสแต็กอาร์กิวเมนต์
Zasz

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

สิ่งนี้จะทำการแทรกตัวแปรทั้งหมดจากนั้นเรียกสตริงผลลัพธ์ วิธีที่คุณมีตอนนี้ดูเหมือนว่า robocopy จะถูกเรียกใช้พร้อมกับเครื่องหมายคำพูดรอบตัวเลือกทั้งหมดเช่น robocopy "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 ..  

}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.