Может ли Windows встроить ZIP-сжатие в сценарий? - PullRequest
59 голосов
/ 27 августа 2008

Можно ли вообще создавать сценарии сжатия ZIP, встроенного в Windows XP / Vista / 2003/2008? Какой исполняемый файл мне нужно будет вызвать из файла BAT / CMD? или это можно сделать с помощью VBScript?

Я понимаю, что это возможно, используя WinZip , 7-Zip и другие внешние приложения, но я ищу то, что не требует установки внешних приложений.

Ответы [ 6 ]

32 голосов
/ 27 августа 2008

Существуют методы VBA для zip и unzip с использованием также встроенных в сжатие окон, что должно дать некоторое представление о том, как работает система. Возможно, вы сможете встроить эти методы в язык сценариев по вашему выбору.

Основной принцип заключается в том, что в Windows вы можете рассматривать zip-файл как каталог и копировать в него и из него. Итак, чтобы создать новый zip-файл, вы просто создаете файл с расширением .zip, который имеет правильный заголовок для пустого zip-файла. Затем вы закрываете его и говорите Windows, что хотите скопировать в него файлы, как если бы это был другой каталог.

Распаковать проще - просто относитесь к нему как к каталогу.

В случае, если веб-страницы снова теряются, вот несколько соответствующих фрагментов кода:

ZIP

Sub NewZip(sPath)
'Create empty Zip File
'Changed by keepITcool Dec-12-2005
    If Len(Dir(sPath)) > 0 Then Kill sPath
    Open sPath For Output As #1
    Print #1, Chr$(80) & Chr$(75) & Chr$(5) & Chr$(6) & String(18, 0)
    Close #1
End Sub


Function bIsBookOpen(ByRef szBookName As String) As Boolean
' Rob Bovey
    On Error Resume Next
    bIsBookOpen = Not (Application.Workbooks(szBookName) Is Nothing)
End Function


Function Split97(sStr As Variant, sdelim As String) As Variant
'Tom Ogilvy
    Split97 = Evaluate("{""" & _
                       Application.Substitute(sStr, sdelim, """,""") & """}")
End Function

Sub Zip_File_Or_Files()
    Dim strDate As String, DefPath As String, sFName As String
    Dim oApp As Object, iCtr As Long, I As Integer
    Dim FName, vArr, FileNameZip

    DefPath = Application.DefaultFilePath
    If Right(DefPath, 1) <> "\" Then
        DefPath = DefPath & "\"
    End If

    strDate = Format(Now, " dd-mmm-yy h-mm-ss")
    FileNameZip = DefPath & "MyFilesZip " & strDate & ".zip"

    'Browse to the file(s), use the Ctrl key to select more files
    FName = Application.GetOpenFilename(filefilter:="Excel Files (*.xl*), *.xl*", _
                    MultiSelect:=True, Title:="Select the files you want to zip")
    If IsArray(FName) = False Then
        'do nothing
    Else
        'Create empty Zip File
        NewZip (FileNameZip)
        Set oApp = CreateObject("Shell.Application")
        I = 0
        For iCtr = LBound(FName) To UBound(FName)
            vArr = Split97(FName(iCtr), "\")
            sFName = vArr(UBound(vArr))
            If bIsBookOpen(sFName) Then
                MsgBox "You can't zip a file that is open!" & vbLf & _
                       "Please close it and try again: " & FName(iCtr)
            Else
                'Copy the file to the compressed folder
                I = I + 1
                oApp.Namespace(FileNameZip).CopyHere FName(iCtr)

                'Keep script waiting until Compressing is done
                On Error Resume Next
                Do Until oApp.Namespace(FileNameZip).items.Count = I
                    Application.Wait (Now + TimeValue("0:00:01"))
                Loop
                On Error GoTo 0
            End If
        Next iCtr

        MsgBox "You find the zipfile here: " & FileNameZip
    End If
End Sub

UNZIP

Sub Unzip1()
    Dim FSO As Object
    Dim oApp As Object
    Dim Fname As Variant
    Dim FileNameFolder As Variant
    Dim DefPath As String
    Dim strDate As String

    Fname = Application.GetOpenFilename(filefilter:="Zip Files (*.zip), *.zip", _
                                        MultiSelect:=False)
    If Fname = False Then
        'Do nothing
    Else
        'Root folder for the new folder.
        'You can also use DefPath = "C:\Users\Ron\test\"
        DefPath = Application.DefaultFilePath
        If Right(DefPath, 1) <> "\" Then
            DefPath = DefPath & "\"
        End If

        'Create the folder name
        strDate = Format(Now, " dd-mm-yy h-mm-ss")
        FileNameFolder = DefPath & "MyUnzipFolder " & strDate & "\"

        'Make the normal folder in DefPath
        MkDir FileNameFolder

        'Extract the files into the newly created folder
        Set oApp = CreateObject("Shell.Application")

        oApp.Namespace(FileNameFolder).CopyHere oApp.Namespace(Fname).items

        'If you want to extract only one file you can use this:
        'oApp.Namespace(FileNameFolder).CopyHere _
         'oApp.Namespace(Fname).items.Item("test.txt")

        MsgBox "You find the files here: " & FileNameFolder

        On Error Resume Next
        Set FSO = CreateObject("scripting.filesystemobject")
        FSO.deletefolder Environ("Temp") & "\Temporary Directory*", True
    End If
End Sub
26 голосов
/ 24 сентября 2008

Да, это может быть написано с помощью VBScript. Например, следующий код может создать почтовый индекс из каталога:

Dim fso, winShell, MyTarget, MySource, file
Set fso = CreateObject("Scripting.FileSystemObject")
Set winShell = createObject("shell.application")


MyTarget = Wscript.Arguments.Item(0)
MySource = Wscript.Arguments.Item(1)

Wscript.Echo "Adding " & MySource & " to " & MyTarget

'create a new clean zip archive
Set file = fso.CreateTextFile(MyTarget, True)
file.write("PK" & chr(5) & chr(6) & string(18,chr(0)))
file.close

winShell.NameSpace(MyTarget).CopyHere winShell.NameSpace(MySource).Items

do until winShell.namespace(MyTarget).items.count = winShell.namespace(MySource).items.count
    wscript.sleep 1000 
loop

Set winShell = Nothing
Set fso = Nothing

Вы также можете найти http://www.naterice.com/blog/template_permalink.asp?id=64 полезным, поскольку он включает в себя полную реализацию Unzip / Zip в VBScript.

Если вы выполняете проверку размера каждые 500 мс, а не количество элементов, это работает лучше для больших файлов. Win 7 записывает файл мгновенно, хотя сжатие еще не закончено:

set fso=createobject("scripting.filesystemobject")
Set h=fso.getFile(DestZip)
do
    wscript.sleep 500
    max = h.size
loop while h.size > max 

Отлично работает с огромным количеством файлов журналов.

5 голосов
/ 04 января 2009

Просто для ясности: GZip не является алгоритмом только для MS, как это предложил Гай Старбак в своем комментарии от августа. GZipStream в System.IO.Compression использует алгоритм Deflate, так же, как библиотека zlib и многие другие инструменты zip. Этот класс полностью совместим с утилитами Unix, такими как gzip.

Класс GZipStream не предназначен для создания сценариев из командной строки или VBScript для создания ZIP-файлов, поэтому он сам по себе не будет ответом на запрос оригинального автора.

Бесплатная библиотека DotNetZip может считывать и создавать zip-файлы и может создаваться в сценариях из VBScript или Powershell. Он также включает в себя инструменты командной строки для создания и чтения / распаковки zip-файлов.

Вот код для VBScript:

dim filename 
filename = "C:\temp\ZipFile-created-from-VBScript.zip"

WScript.echo("Instantiating a ZipFile object...")
dim zip 
set zip = CreateObject("Ionic.Zip.ZipFile")

WScript.echo("using AES256 encryption...")
zip.Encryption = 3

WScript.echo("setting the password...")
zip.Password = "Very.Secret.Password!"

WScript.echo("adding a selection of files...")
zip.AddSelectedFiles("*.js")
zip.AddSelectedFiles("*.vbs")

WScript.echo("setting the save name...")
zip.Name = filename

WScript.echo("Saving...")
zip.Save()

WScript.echo("Disposing...")
zip.Dispose()

WScript.echo("Done.")

Вот код для Powershell:

[System.Reflection.Assembly]::LoadFrom("c:\\dinoch\\bin\\Ionic.Zip.dll");

$directoryToZip = "c:\\temp";
$zipfile =  new-object Ionic.Zip.ZipFile;
$e= $zipfile.AddEntry("Readme.txt", "This is a zipfile created from within powershell.")
$e= $zipfile.AddDirectory($directoryToZip, "home")
$zipfile.Save("ZipFiles.ps1.out.zip");

В файле .bat или .cmd вы можете использовать инструменты zipit.exe или unzip.exe. Например:

zipit NewZip.zip  -s "This is string content for an entry"  Readme.txt  src 
2 голосов
/ 22 января 2015

Вот моя попытка суммировать окна встроенных возможностей для сжатия и распаковки - Как я могу сжимать (/ zip) и распаковывать (/ unzip) файлы и папки с пакетным файлом без использования каких-либо внешних инструментов?

с несколькими указанными решениями, которые должны работать практически на каждом компьютере с Windows.

Что касается shell.application и WSH, я предпочел jscript поскольку он позволяет использовать гибридный пакетный / jscript-файл (с расширением .bat), для которого не требуются временные файлы. Я поместил в один файл функции распаковки и архивирования, а также несколько дополнительных функций.

1 голос
/ 26 февраля 2013

для создания сжатого архива вы можете использовать утилиту MAKECAB.EXE

1 голос
/ 27 августа 2008

В пакете UnxUtils, доступном в SourceForge, есть как исполняемые файлы zip, так и unzip (а также множество других полезных приложений) (http://sourceforge.net/projects/unxutils).. Скопируйте их в папку в вашем PATH, например, 'c: \ windows ', и вы сможете включить их в свои скрипты.

Это не идеальное решение (или то, о котором вы просили), а достойное решение проблемы.

...