wake-up-neo.com

Powershell 2 Copy-Element, das einen Ordner erstellt, falls nicht vorhanden

$from = "\\something\1 XLS\2010_04_22\*"
$to =  "c:\out\1 XLS\2010_04_22\"
copy-item $from $to -Recurse 

Dies funktioniert, wenn c:\out\1 XLS\2010_04_22\vorhanden ist. Ist es mit einem einzigen Befehl möglich, "c:\out\1 XLS\2010_04_22 \" zu erstellen, wenn es nicht existiert.

54
MicMit

Ja, fügen Sie den Parameter -Force hinzu. 

copy-item $from $to -Recurse -Force
70
Shay Levy

In PowerShell 2.0 ist es immer noch nicht möglich, das Cmdlet Copy-Item zum Erstellen des Zielordners abzurufen. Sie benötigen folgenden Code:

$destinationFolder = "C:\My Stuff\Subdir"

if (!(Test-Path -path $destinationFolder)) {New-Item $destinationFolder -Type Directory}
Copy-Item "\\server1\Upgrade.exe" -Destination $destinationFolder

Wenn Sie -Recurse im Copy-Item verwenden, werden alle Unterordner der Quellstruktur im Ziel erstellt, jedoch nicht der eigentliche Zielordner, auch nicht mit -orce.

91
FrinkTheBrave

In PowerShell 3 und höher verwende ich das Copy-Item mit New-Item.

copy-item -Path $file -Destination (new-item -type directory -force ("C:\Folder\sub\sub\" + $newSub)) -force -ea 0

Ich habe es in Version 2 nicht probiert.

10
mjudd
function Copy-File ([System.String] $sourceFile, [System.String] $destinationFile, [Switch] $overWrite) {

    if ($sourceFile -notlike "filesystem::*") {
        $sourceFile = "filesystem::$sourceFile" 
    }

    if ($destinationFile -notlike "filesystem::*") {
        $destinationFile = "filesystem::$destinationFile" 
    }

    $destinationFolder = $destinationFile.Replace($destinationFile.Split("\")[-1],"")

    if (!(Test-Path -path $destinationFolder)) {
        New-Item $destinationFolder -Type Directory
    }

    try {
        Copy-Item -Path $sourceFile -Destination $destinationFile -Recurse -Force
        Return $true 
    } catch [System.IO.IOException] {
        # If overwrite enabled, then delete the item from the destination, and try again:
        if ($overWrite) {
            try {
                Remove-Item -Path $destinationFile -Recurse -Force        
                Copy-Item -Path $sourceFile -Destination $destinationFile -Recurse -Force 
                Return $true
            } catch {
                Write-Error -Message "[Copy-File] Overwrite error occurred!`n$_" -ErrorAction SilentlyContinue
                #$PSCmdlet.WriteError($Global:Error[0])
                Return $false
            }
        } else {
            Write-Error -Message "[Copy-File] File already exists!" -ErrorAction SilentlyContinue
            #$PSCmdlet.WriteError($Global:Error[0])
            Return $false
        }
    } catch {
        Write-Error -Message "[Copy-File] File move failed!`n$_" -ErrorAction SilentlyContinue
        #$PSCmdlet.WriteError($Global:Error[0]) 
        Return $false
    } 
}
2
Bart

Mein Favorit ist die .Net-Klasse [IO.DirectoryInfo], die sich um einige Logik kümmert. Ich benutze das eigentlich für viele ähnliche Herausforderungen beim Scripting. Es hat eine .Create () -Methode, die Verzeichnisse erstellt, die nicht vorhanden sind, ohne dass Fehler auftreten.

Da dies immer noch ein zweistufiges Problem ist, verwende ich den Alias ​​foreach, um es einfach zu halten. Für einzelne Dateien:

[IO.DirectoryInfo]$to |% {$_.create(); cp $from $_}

Soweit Ihre Datei/Verzeichnis übereinstimmen, würde ich RoboCopy über Xcopy verwenden. Entfernen Sie das "*" von Ihrem und benutzen Sie einfach:

RoboCopy.exe $from $to *

Sie können weiterhin/r (Recurse),/e (Recurse einschließlich Empty) hinzufügen, und es gibt 50 weitere nützliche Schalter.

Edit: Rückblickend ist es knapp, aber nicht sehr gut lesbar, wenn Sie den Code nicht oft verwenden. Normalerweise habe ich es in zwei Hälften geteilt:

([IO.DirectoryInfo]$to).Create()
cp $from $to

DirectoryInfo ist auch der Typ der Parent-Eigenschaft von FileInfo. Wenn Ihr $ bis eine Datei ist, können Sie sie zusammen verwenden:

([IO.FileInfo]$to).Parent.Create()
cp $from $to
2

Hier ist ein Beispiel, das für mich funktioniert hat. Ich hatte eine Liste von ungefähr 500 spezifischen Dateien in einer Textdatei, die in ungefähr 100 verschiedenen Ordnern enthalten war und die ich an einen Sicherungsort kopieren sollte, falls diese Dateien später benötigt würden. Die Textdatei enthielt den vollständigen Pfad und den Dateinamen, einen pro Zeile. In meinem Fall wollte ich den Laufwerksbuchstaben und den ersten Unterordnernamen von jedem Dateinamen entfernen. Ich wollte alle diese Dateien in eine ähnliche Ordnerstruktur unter einem anderen angegebenen Stammzielordner kopieren. Ich hoffe, andere Benutzer finden dies hilfreich.

# Copy list of files (full path + file name) in a txt file to a new destination, creating folder structure for each file before copy
$rootDestFolder = "F:\DestinationFolderName"
$sourceFiles = Get-Content C:\temp\filelist.txt
foreach($sourceFile in $sourceFiles){
    $filesplit = $sourceFile.split("\")
    $splitcount = $filesplit.count
    # This example strips the drive letter & first folder ( ex: E:\Subfolder\ ) but appends the rest of the path to the rootDestFolder
    $destFile = $rootDestFolder + "\" + $($($sourceFile.split("\")[2..$splitcount]) -join "\")
    # Output List of source and dest 
    Write-Host ""
    Write-Host "===$sourceFile===" -ForegroundColor Green
    Write-Host "+++$destFile+++"
    # Create path and file, if they do not already exist
    $destPath = Split-Path $destFile
    If(!(Test-Path $destPath)) { New-Item $destPath -Type Directory }
    If(!(Test-Path $destFile)) { Copy-Item $sourceFile $destFile }
}
2
Toby Bierly
  $filelist | % {
    $file = $_
    mkdir -force (Split-Path $dest) | Out-Null
    cp $file $dest
  } 
2
majkinetor

Ich bin hier zweimal gestolpert, und das letzte Mal war eine einzigartige Situation, und obwohl ich mit copy-item Schluss machte, wollte ich die Lösung posten, die ich verwendete. 

Hatte eine Liste von nichts außer Dateien mit dem vollständigen Pfad und in den meisten Fällen haben die Dateien keine Erweiterungen. Die -Recurse -Force-Option würde für mich nicht funktionieren, also habe ich copy-item-Funktion aufgegeben und bin auf xcopy zurückgefallen, da ich immer noch einen One-Liner behalten wollte. Ich habe mich anfangs mit Robocopy zusammengetan, sucht aber offenbar nach einer Dateierweiterung und da viele von mir keine Erweiterung hatten, betrachtete es dies als Verzeichnis.

$filelist = @("C:\Somepath\test\location\here\file","C:\Somepath\test\location\here2\file2")

$filelist | % { echo f | xcopy $_  $($_.Replace("somepath", "somepath_NEW")) }

Hoffe es hilft jemandem. 

0
ssaviers