Robocopy powershell içinde çalışan nasıl?


24

Powershell içinde robokopi kullanmaya çalışıyorum. İşte betiğim:

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

Komut dosyası, kaynak ve hedef dizinlerin listesini içeren bir csv dosyasında bulunur. Senaryoyu çalıştırdığımda şu hataları alıyorum:

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

Düzeltmek için ne yapmam gerektiğini bilen var mı?

Sağol Mark.

Yanıtlar:


10

İçin değişkenler ise $whatve $optionsdeğişmez, neden değişkenler?

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

Bu benim için iyi çalışıyor:

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

İyi nokta - basit olsun. :)
Helvick

3
Ayrıca / sn değil / sn / burada kritiktir

1
Yani / Log'u atladınız ve işe yaradı :-) Gotcha, önceden Logfile bulunmadığında PS ile Robocopy'yi çağıran garip Hatalar almanız.
icnivad

6
Bunun eski bir yazı olduğunu biliyorum, ancak bence değişken olarak bunları kullanmanın, betiğin gelecekteki okurlarına bu betiğin yapılandırılabilir parçaları olması gerektiğini belirtiyor. Bunun işe yaramasının nedeni, yazım hatasını orijinal $ $ içinde düzeltmek oluyor.
Ahtapot,

2
Bir şey değişmese bile, değişken kapsülleme bir betiği daha az karmaşık hale getirmeye yardımcı olabilir. Ve eğer ortaya çıkarsa, bu değişkene daha sonra tekrar başvurmam gerekiyor, senaryoyu daha dinamik kılıyor
Kolob Canyon

20

Dizeleri Powershell içinden harici komutlar için parametrelere yerleştirmek, değişken genişletmeyi kullanabilmek ve ayrıca hangi komut satırının hangi parametreleri ayırmak istediğinizi ve hangilerinin ayırmaması gerektiğini doğru bir şekilde anlayabilmeniz için bir miktar atlama işlemi gerektirir. Örneğinizde, dizenin tamamını ilk parametre olarak gönderiyorsunuz ve Robocopy, size bu uzun dizeyi bir kaynak dizin olarak bulamadığını söylüyor. Kaynak dizenin tamamının tek bir param olarak kabul edilmesini istiyorsunuz (orada olabilecek boşluklar dahil), Hedef için de aynı şekilde ancak $ what ve $ seçenekleriniz başarısız olacak çünkü ikisi de Robocopy'ye tek bir parametre olarak teslim edilemeyecek. çözümlenir.

Bunu doğru yapmanın birkaç yolu vardır, ancak aşağıdaki kod parçası parametrelerinizi çözmek istediğiniz görünüme dayanır ve kullandığım tek dizin örneği için işe yarar.

$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

Yanıt için teşekkürler. Kodunuzu denedim ancak hala aşağıdaki hatayı alıyorum: HATA: Geçersiz Parametre # 3: "/ COPYALL / B / SEC / MIR"
Mark Allison

Yukarıdaki saplama kodunu çalıştırdığımda (yukarıdan kopyalandı) tam olarak beklendiği gibi çalışıyor - özellikle tüm options \ hangi öğelerin ayrı parametreler olarak tanındığını. Sadece yukarıdaki saplama çalıştırırsanız (var olan bir kaynak klasörle) işe yarıyor mu? Eğer öyleyse, değiştirilmiş kodunuzda Quotes \ kaçan karakterini iki kez kontrol edin. Geçersiz parametre # 3, çalıştırdığınız koddaki ayrı parametrelerin bir dizisi değil, hala tek bir dize olan sürümünüzün olduğunu gösterir.
Helvick

2
+1. Burada kesinlikle sorun bu. İnsanların sürekli PowerShell'i eski, salt metin tabanlı bir kabukluymuş gibi kullanmaya çalıştıklarını komik buluyorum ;-)
Joey

@Joey Powershell nesne modelini, metin temelli olanlardan daha pratikte daha iyi sonuç bulabildiniz mi?
Didier A.

1
@DidierA .: Kesinlikle. Özellikle nesneleri etkileşim ile, örneğin dosyalar, işlemler, hizmet vb Ama sadece yerel uygulamalar ve dize çıkışları olduğunda bile, sadece olağan dize kullanabilirsiniz, örneğin şeyleri açıklamak için var olduğu -matchve -replace/ projeksiyon cmdlet'lerinizi filtreleme yanı sıra Bununla çalışmak için. Genel olarak bu konuda oldukça iyi tasarlanmıştır (çoğu *-Objectkomut ortogonaldir ve hepsi herhangi bir nesneye uygulanabilir).
Joey

3

Robocopy çizgisinden alıntılar kaldırılsın mı?

yani

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
}

Hayır, önce bunu denedim ve işe yaramadı (benzer hatalar), bu yüzden yukarıda gösterileni değiştirdim. Başka fikrin var mı?
Mark Allison,

Tırnak olmadan çalıştırdığınızda çıktı nedir? Kaynağı "P: \ C: \ Yedekleme \ Fotoğraflar \ COPYALL \ B \ SEC \ \ MIR \ R: 0 \ W: 0 \ NFL \ NDL \ LOG: MyLogfile.txt \" olarak gösteren orijinal çıktınız benim çizdiğim şeydi. alıntılara dikkat.
Bryan,

3

Ben de aynı problemi yaşadım. Komut satırının tamamı ilk argüman olarak yorumlandı.

Yukarıda belirtilen hiçbir şey dahil olmak üzere çalıştı:

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

Tırnaklardan çıkmak, yolda bir boşluk olduğunda işe yaramaz:

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

Http://edgylogic.com/blog/powershell-and-external-commands-done-right/ adresindeki püf noktaları denedikten sonra sonunda anladım.

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

Belki de yarasa dosyalarına takılmalıydım. :)


Edgylogic için bağlantı taşındı slai.github.io/posts/... ?
Henrik Staun Poulsen

1

Yerel bir komutu yürütmenin en iyi yolunun dizelerin bir listesini çalıştırmak için & komutunu kullanmak olduğunu buldum. Ayrıca, konsol çıktısının bir powershell transkriptine dahil edilmesini istiyorsanız, çıkışı ana makineye yönlendirmeniz gerekir. İşte yazdığım 7- Zip'den Amazon S3 Powershell Komut Dosyasına alınan birden fazla parametreyle 7Zip'i çağırmanın bir örneği :

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

Temelde durumunuz için şöyle bir şey denerdim ($ $ ve $ options parametrelerini ayrı ayrı ayırmanız gerekebilir):

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

Bununla ilgili sorun, “$ what” ve “$ options” dediğiniz gibi, ayrı olanların bir listesi yerine tek bir parametre olarak robokopiye gönderilecek ve örnek kodunu verdiklerinde, çözülmeleri gerekmeyecek olmasıdır. o.
Helvick

@Virgülle ayrılmış bir listeyi argüman yığına bölmek için powershell v3 kullanıyorsanız, splat operatörünü kullanabilirsiniz
Zasz

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

Bu, tüm değişkenleri enterpolasyona sokar, ardından sonuç dizesini çağırır. Şimdi sahip olduğunuz şekilde, robokopi tüm seçeneklerin etrafındaki tırnak işaretleriyle çağrılıyor gibi görünüyor, yani robokopi "c: \ src c: \ dst blah meh". Bu tek bir parametre olarak yorumlanır.


0

Bu benim için çalıştı ve günlük dosyası konumunun dinamik bir girişini sağlar. & sembolü sadece PowerShell'e metnin çalıştırmak istediğim bir kod satırı olduğunu söyler.

    $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

Buna 2 kuruş ekleyerek birine yardımcı olabilir ... Aşağıdaki kod, kopyalanacak dosyaları almak için bir csv okuduğum "loop" kısmını eksik.

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

}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.