Làm thế nào để có được robocopy chạy trong powershell?


24

Tôi đang cố gắng sử dụng robocopy bên trong powershell để phản chiếu một số thư mục trên các máy gia đình của tôi. Đây là kịch bản của tôi:

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

Kịch bản có trong một tệp csv với một danh sách các thư mục nguồn và đích. Khi tôi chạy tập lệnh, tôi gặp các lỗi sau:

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

Bất cứ ý tưởng những gì tôi cần phải làm để sửa chữa?

Cảm ơn, Mark.

Câu trả lời:


10

Nếu các biến cho $what$optionskhông thay đổi, tại sao chúng là biến?

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

Cái này làm việc tốt cho tôi:

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

Điểm tốt - giữ cho nó đơn giản. :)
Helvick

3
cũng / giây không / giây / là rất quan trọng ở đây

1
Vì vậy, bạn chỉ cần bỏ qua / Nhật ký và nó đã hoạt động :-) Gotcha là bạn gặp phải lỗi lạ khi gọi Robocopy với PS khi Logfile không tồn tại trước đó.
icnivad

6
Tôi biết đây là một bài viết cũ, nhưng tôi nghĩ rằng đáng để nói rằng việc có những biến này là một tín hiệu cho những người đọc tương lai của tập lệnh rằng chúng có nghĩa là những phần có thể cấu hình được của tập lệnh. Lý do điều này hoạt động là nó xảy ra để sửa lỗi chính tả trong $ ban đầu.
Bạch tuộc

2
Ngay cả khi một cái gì đó không thay đổi, đóng gói biến có thể giúp làm cho một kịch bản ít phức tạp hơn. Và nếu hóa ra tôi cần tham khảo biến đó một lần nữa sau đó, nó làm cho kịch bản trở nên năng động hơn
Kolob Canyon

20

Việc nhập chuỗi vào tham số cho các lệnh bên ngoài từ bên trong Powershell yêu cầu một số bước nhảy nếu bạn muốn có thể sử dụng mở rộng biến và cũng có dòng lệnh kết quả hiểu chính xác tham số nào bạn muốn tách và không nên tham số. Trong ví dụ của bạn, bạn đang gửi toàn bộ chuỗi dưới dạng tham số đầu tiên và Robocopy đang nói với bạn rằng nó không thể tìm thấy chuỗi dài đó dưới dạng thư mục nguồn. Bạn muốn toàn bộ chuỗi Nguồn được coi là một tham số (bao gồm cả khoảng trắng có thể có trong đó), tương tự cho Đích nhưng các tùy chọn $ what và $ của bạn sẽ thất bại vì cả hai sẽ được gửi đến Robocopy dưới dạng một tham số duy nhất không thể có phân tích cú pháp.

Có một số cách để làm điều này đúng nhưng đoạn mã sau dựa trên cách bạn dường như muốn thoát ra các tham số của mình và không hoạt động cho ví dụ thư mục duy nhất tôi đã sử dụng.

$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

Cảm ơn vi đa trả lơi. Tôi đã thử mã của bạn nhưng tôi vẫn nhận được lỗi sau: LRI: Thông số không hợp lệ # 3: "/ COPUALL / B / SEC / MIR"
Đánh dấu Allison

Khi tôi chạy mã sơ khai ở trên (được sao chép từ phía trên), nó hoạt động chính xác như mong đợi - cụ thể là tất cả các tùy chọn \ mục nào được nhận dạng là tham số riêng biệt. Nếu bạn chỉ chạy sơ khai ở trên (với một thư mục nguồn tồn tại) thì nó có hoạt động không? Nếu vậy, hãy kiểm tra lại Dấu ngoặc kép \ thoát trong mã sửa đổi của riêng bạn. Tham số không hợp lệ # 3 chỉ ra rằng phiên bản $ của bạn vẫn là một chuỗi không phải là một mảng các tham số riêng biệt trong mã bạn đang chạy.
Helvick

2
+1. Đó chắc chắn là vấn đề ở đây. Tôi thấy buồn cười khi mọi người liên tục cố gắng sử dụng PowerShell như thể nó là một vỏ dựa trên văn bản cũ ;-)
Joey

@Joey Bạn đã tìm thấy mô hình đối tượng của powershell để hoạt động tốt hơn trong thực tế so với mô hình dựa trên văn bản chưa?
Didier A.

1
@DidierA.: Chắc chắn. Đặc biệt là nơi các đối tượng tồn tại để mô tả những điều bạn tương tác với, ví dụ như các file, các tiến trình, dịch vụ, vv Tuy nhiên, ngay cả khi bạn chỉ có các ứng dụng bản địa và kết quả đầu ra chuỗi bạn chỉ có thể sử dụng các toán tử chuỗi thông thường, ví dụ -match-replacecũng như lọc / cmdlet chiếu để làm việc với điều đó. Nó thường được thiết kế khá tốt trong vấn đề đó (hầu hết *-Objectcác lệnh là trực giao và tất cả chúng đều có thể được áp dụng cho bất kỳ đối tượng nào).
Joey

3

Loại bỏ các trích dẫn từ dòng robocopy?

I E

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
}

Không, tôi đã thử trước và nó không hoạt động (lỗi tương tự), vì vậy tôi đã thay đổi nó thành những gì được hiển thị ở trên. Còn ý tưởng nào khác không?
Đánh dấu Allison

Đầu ra là gì khi bạn chạy nó mà không có dấu ngoặc kép? Đầu ra ban đầu của bạn hiển thị Nguồn là "P: \ C: \ Backup \ Photos \ COPUALL \ B \ SEC \ \ MIR \ R: 0 \ W: 0 \ NFL \ NDL \ LOG: MyLogfile.txt \" là những gì đã thu hút tôi chú ý đến các trích dẫn.
Bryan

3

Tôi đã từng gặp vấn đề tương tự. Toàn bộ dòng lệnh được hiểu là đối số đầu tiên.

Không có gì được đề cập ở trên bao gồm:

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

Bỏ các trích dẫn không hoạt động khi có một khoảng trống trên đường dẫn:

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

Sau khi thử các thủ thuật trong http://edgylogic.com/blog/powershell-and-external-commands-done-right/ , cuối cùng tôi đã hiểu.

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

Có lẽ tôi nên bị mắc kẹt với các tập tin bat. :)


Liên kết của bạn đến edgylogic đã được chuyển đến slai.github.io/posts/ chưa?
Henrik Staun Poulsen

1

Tôi đã thấy rằng cách tốt nhất để thực thi lệnh gốc là sử dụng lệnh & để thực thi danh sách các chuỗi. Ngoài ra nếu bạn muốn đầu ra của giao diện điều khiển được bao gồm trong bảng điểm powershell, bạn sẽ cần chuyển đầu ra ra khỏi máy chủ. Dưới đây là một ví dụ về cách gọi 7Zip với nhiều tham số được lấy từ Tập lệnh Powershell 7-Zip sang Amazon S3 mà tôi đã viết:

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

Về cơ bản cho trường hợp của bạn, tôi sẽ thử một cái gì đó như thế này (có thể cần phải tách ra các tham số tùy chọn $ what và $):

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

Vấn đề với điều này là khi bạn nói "$ what" và "$ tùy chọn" sẽ được gửi đến robocopy dưới dạng một tham số riêng lẻ thay vì một danh sách các tham số riêng biệt và được cung cấp mã mẫu của anh ấy, chúng sẽ không bị phá vỡ nó
Helvick

Bạn có thể sử dụng toán tử splat @nếu bạn đang sử dụng powershell v3 để phân chia danh sách được phân tách bằng dấu phẩy thành ngăn xếp đối số
Zasz

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

Điều này sẽ nội suy tất cả các biến, sau đó gọi chuỗi kết quả. Theo cách bạn có bây giờ, có vẻ như robocopy đang được gọi với các trích dẫn xung quanh tất cả các tùy chọn, tức là, robocopy "c: \ src c: \ dst blah meh". Điều này được hiểu là một tham số duy nhất.


0

Điều này làm việc cho tôi và cho phép một đầu vào động của vị trí tệp nhật ký. biểu tượng & chỉ cho PowerShell biết rằng văn bản là một dòng mã tôi muốn chạy.

    $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

Thêm 2 xu của tôi vào đây vì nó có thể giúp ai đó ... Đoạn mã dưới đây thiếu phần "vòng lặp" nơi tôi đọc một csv để lấy các tệp để sao chép

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

}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.