web-dev-qa-db-fra.com

Création d'un dossier compressé / compressé dans Windows à l'aide de Powershell ou de la ligne de commande

Je crée un fichier de schéma de base de données tous les soirs et j'aimerais mettre tous les fichiers créés chaque nuit, un pour chaque base de données, dans un dossier et compresser ce dossier. J'ai un script PowerShell qui crée le schéma. Seul le script de création de la base de données, puis ajoute tous les fichiers dans un nouveau dossier. Le problème réside dans la partie compression de ce processus.

Quelqu'un a-t-il une idée si cela peut être accompli avec l'utilitaire Windows préinstallé qui gère la compression des dossiers?

Il serait préférable d'utiliser cet utilitaire si possible plutôt que quelque chose comme 7Zip (je n'ai pas envie d'installer 7Zip sur le serveur de chaque client et cela peut prendre des années informatiques pour le faire si je le leur demande).

23
TechDawg270

Voici quelques fonctions liées à Zip qui ne dépendent pas d'extensions: Compression de fichiers avec Windows PowerShell .

La fonction principale qui pourrait vous intéresser est:

function Add-Zip
{
    param([string]$zipfilename)

    if(-not (test-path($zipfilename)))
    {
        set-content $zipfilename ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18))
        (dir $zipfilename).IsReadOnly = $false  
    }

    $shellApplication = new-object -com Shell.application
    $zipPackage = $shellApplication.NameSpace($zipfilename)

    foreach($file in $input) 
    { 
            $zipPackage.CopyHere($file.FullName)
            Start-sleep -milliseconds 500
    }
}

Usage:

dir c:\demo\files\*.* -Recurse | Add-Zip c:\demo\myzip.Zip

Il y a une mise en garde: la fonction NameSpace() de l'objet Shell.application N'ouvre pas le fichier Zip pour l'écriture si le chemin n'est pas absolu. Donc, si vous avez passé un chemin relatif à Add-Zip, Il échouera avec une erreur nulle, donc le chemin vers le fichier Zip doit être absolu.

Ou vous pouvez simplement ajouter un $zipfilename = resolve-path $zipfilename Au début de la fonction.

20
voithos

Une manière native avec le dernier framework .NET 4.5, mais entièrement sans fonctionnalités:

Création:

Add-Type -Assembly "System.IO.Compression.FileSystem" ;
[System.IO.Compression.ZipFile]::CreateFromDirectory("c:\your\directory\to\compress", "yourfile.Zip") ;

Extraction:

Add-Type -Assembly "System.IO.Compression.FileSystem" ;
[System.IO.Compression.ZipFile]::ExtractToDirectory("yourfile.Zip", "c:\your\destination") ;

Comme mentionné, totalement sans fonctionnalités, ne vous attendez donc pas à un indicateur écraser.

23
sonjz

À partir de Powershell 5, il existe une applet de commande Compress-Archive qui effectue la tâche hors de la boîte.

7
Overly Excessive

Cela compresse le contenu.\In en.\Out.Zip avec System.IO.Packaging.ZipPackage en suivant l'exemple ici

$zipArchive = $pwd.path + "\out.Zip"
[System.Reflection.Assembly]::Load("WindowsBase,Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")
$ZipPackage=[System.IO.Packaging.ZipPackage]::Open($zipArchive, [System.IO.FileMode]"OpenOrCreate", [System.IO.FileAccess]"ReadWrite")
$in = gci .\in | select -expand fullName
[array]$files = $in -replace "C:","" -replace "\\","/"
ForEach ($file In $files) {
   $partName=New-Object System.Uri($file, [System.UriKind]"Relative")
   $part=$ZipPackage.CreatePart($partName, "application/Zip", [System.IO.Packaging.CompressionOption]"Maximum")
   $bytes=[System.IO.File]::ReadAllBytes($file)
   $stream=$part.GetStream()
   $stream.Write($bytes, 0, $bytes.Length)
   $stream.Close()
                                                    }
$ZipPackage.Close()
2
noam

Utilisé la réponse de voithos aux fichiers Zip dans PowerShell, juste eu un problème avec la fonction Add-Zip, le Start-sleep-milliseconds 500 a causé des problèmes si le fichier ne pouvait pas être complètement zippé pendant ce temps -> le suivant commençant avant qu'il ne soit terminé, des erreurs et certains fichiers n'ont pas été compressés.

Donc, après avoir joué un peu, essayez d'abord d'obtenir un compteur pour vérifier le nombre de $ zipPackage.Items () et continuez seulement après que le nombre d'éléments ait augmenté (ce qui n'a pas fonctionné car il retournerait 0 dans certains cas quand il ne devrait pas) J'ai trouvé qu'il retournera 0 si le paquet zippe/copie toujours les fichiers (je pense, haha). Ajout d'une simple boucle while avec le start-sleep à l'intérieur, en attendant que le zipPackage.Items (). Count soit une valeur non nulle avant de continuer et cela semble résoudre le problème.

function Add-Zip
{
param([string]$zipfilename)

if(-not (test-path($zipfilename)))
{
    set-content $zipfilename ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18))
    (dir $zipfilename).IsReadOnly = $false  
}

$shellApplication = new-object -com Shell.application
$zipPackage = $shellApplication.NameSpace($zipfilename)

foreach($file in $input) 
{ 
        $zipPackage.CopyHere($file.FullName)
        do
        {
            Start-sleep -milliseconds 250
        }
        while ($zipPackage.Items().count -eq 0)
}
}
2
Verts