Powershell에서 robocopy를 실행하는 방법은 무엇입니까?


24

powershell 내부에서 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"
}

이 스크립트는 소스 및 대상 디렉토리 목록이 포함 된 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는 Logfile이 미리 존재하지 않을 때 PS로 Robocopy를 호출하는 이상한 오류가 발생한다는 것입니다.
icnivad

6
나는 이것이 오래된 게시물이라는 것을 알고 있지만 변수로 변수를 갖는 것이 스크립트의 미래 독자에게 이것이 스크립트의 구성 가능한 부분이라는 신호라고 생각할 가치가 있다고 생각합니다. 이것이 작동하는 이유는 원래 $ what에서 오타를 수정하기 때문입니다.
Octopus

2
변경 사항이없는 경우에도 변수 캡슐화를 사용하면 스크립트의 복잡성을 줄일 수 있습니다. 그리고 나중에이 변수를 다시 참조해야한다면 스크립트가 더욱 역동적입니다.
Kolob Canyon

20

Powershell 내에서 외부 명령에 대한 문자열을 매개 변수에 채우려면 변수 확장을 사용하고 결과 명령 줄에서 분리하려는 매개 변수와 그렇지 않은 매개 변수를 올바르게 이해하려면 약간의 점프 점프가 필요합니다. 귀하의 예에서 전체 문자열을 첫 번째 매개 변수로 보내고 Robocopy는 긴 문자열을 소스 디렉토리로 찾을 수 없음을 알려줍니다. Destination과 마찬가지로 전체 소스 문자열을 하나의 매개 변수 (여기에있을 수있는 공백 포함)로 처리하려고하지만 $ what 및 $ options는 단일 매개 변수로 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

위의 스텁 코드를 실행하면 (위에서 복사) 예상대로 정확하게 작동합니다. 특히 모든 옵션 / 항목이 별도의 매개 변수로 인식됩니다. 위의 스텁 (소스 폴더가있는) 만 실행하면 작동합니까? 그렇다면 자신의 수정 된 코드에서 인용 부호를 다시 확인하십시오. 잘못된 매개 변수 # 3은 $ what 버전이 여전히 실행중인 코드에서 별도의 매개 변수 배열이 아닌 단일 문자열임을 나타냅니다.
Helvick

2
+1. 그것은 분명히 여기서 문제입니다. 사람들이 PowerShell을 마치 텍스트 기반의 오래된 쉘인 것처럼 끊임없이 사용하려고하는 방법이 재미 있다는 것을 알았습니다.
Joey

@Joey 텍스트 기반의 것보다 powershell의 객체 모델이 실제로 더 잘 작동한다는 것을 알았습니까?
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 \"로 표시 한 원본 출력은 따옴표에주의하십시오.
Bryan

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 스크립트에 포함 시키려면 출력을 호스트 외부로 파이프해야합니다. 다음은 7-Zip에서 Amazon S3 Powershell Script로 가져온 여러 매개 변수를 사용하여 7Zip을 호출하는 예입니다 .

$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

@powershell v3을 사용하여 쉼표로 구분 된 목록을 인수 스택으로 분할하는 경우 splat 연산자를 사용할 수 있습니다.
Zasz

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

모든 변수를 보간 한 다음 결과 문자열을 호출합니다. 당신이 지금 가지고있는 방법은 robocopy "c : \ src c : \ dst blah meh"와 같은 모든 옵션 주위에 따옴표로 robocopy가 호출되는 것처럼 보입니다. 이것은 단일 매개 변수로 해석됩니다.


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.