web-dev-qa-db-fra.com

Copier Powershell 2 qui crée un dossier s'il n'existe pas

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

Cela fonctionne si c:\out\1 XLS\2010_04_22\existe. Est-il possible avec une seule commande de créer "c:\out\1 XLS\2010_04_22 \" s'il n'existe pas.

54
MicMit

Oui, ajoutez le paramètre -Force

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

Dans PowerShell 2.0, il n’est toujours pas possible d’obtenir la cmdlet Copy-Item pour créer le dossier de destination, vous aurez besoin d’un code comme celui-ci:

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

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

Si vous utilisez -Recurse dans l'élément de copie, tous les sous-dossiers de la structure source de la destination seront créés, mais le dossier de destination réel ne sera pas créé, même avec -Force.

91
FrinkTheBrave

Dans PowerShell 3 et les versions ultérieures, j'utilise l'élément Copier avec Nouvel élément.

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

Je n'ai pas essayé dans la version 2.

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

Mon préféré est d'utiliser la classe .Net [IO.DirectoryInfo], qui gère une partie de la logique. En fait, je l’utilise pour beaucoup de défis de script similaires. Il a une méthode .Create () qui crée des répertoires qui n'existent pas, sans erreurs s'ils existent.

Comme il s’agit toujours d’un problème en deux étapes, j’utilise l’alias foreach pour que cela reste simple. Pour des fichiers uniques:

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

Pour ce qui est de la correspondance de plusieurs fichiers/répertoires, j'utiliserais RoboCopy sur xcopy. Supprimez le "*" de votre et utilisez simplement:

RoboCopy.exe $from $to *

Vous pouvez toujours ajouter le/r (Recurse),/e (Recurse, y compris un vide), et il existe 50 autres commutateurs utiles.

Edit: En regardant en arrière, il est concis, mais pas très lisible si vous n’utilisez pas souvent le code. Habituellement, je l'ai divisé en deux, comme ceci:

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

De plus, DirectoryInfo est le type de la propriété Parent de FileInfo. Par conséquent, si votre $ à est un fichier, vous pouvez les utiliser ensemble:

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

Voici un exemple qui a fonctionné pour moi. J'avais une liste d'environ 500 fichiers spécifiques dans un fichier texte, contenu dans environ 100 dossiers différents, que j'étais supposé copier sur un emplacement de sauvegarde au cas où ces fichiers seraient nécessaires ultérieurement. Le fichier texte contenait le chemin complet et le nom du fichier, un par ligne. Dans mon cas, je voulais enlever la lettre de lecteur et le nom du premier sous-dossier de chaque nom de fichier. Je voulais copier tous ces fichiers dans une structure de dossiers similaire sous un autre dossier de destination racine que j'ai spécifié. J'espère que les autres utilisateurs trouvent cela utile.

# 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

J'ai trébuché ici deux fois, et cette dernière fois était une situation unique et même si j'ai abandonné l'utilisation de copy-item, je voulais publier la solution que j'ai utilisée. 

Avait une liste de rien, mais les fichiers avec le chemin complet et dans la majorité des cas, les fichiers n'ont pas d'extensions. l'option -Recurse -Force ne fonctionnant pas pour moi, j'ai donc abandonné la fonction copy-item et je suis tombé à quelque chose comme ci-dessous, à l'aide de xcopy, car je souhaitais tout de même conserver une couche. Au départ, j’étais à égalité avec Robocopy, mais cette dernière est apparemment à la recherche d’une extension de fichier et, comme beaucoup d’entre elles n’ont pas d’extension, elle le considère comme un répertoire.

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

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

J'espère que ça aide quelqu'un. 

0
ssaviers