2008-08-27 13 views
53

¿La compresión ZIP que está incorporada en Windows XP/Vista/2003/2008 es capaz de ser guionizada? ¿Qué ejecutable tendría que llamar desde un archivo BAT/CMD? o es posible hacerlo con VBScript?¿Puede la compresión ZIP incorporada de Windows tener secuencias de comandos?

Me doy cuenta de que esto es posible usando WinZip, 7-Zip y otras aplicaciones externas, pero estoy buscando algo que no requiera la instalación de aplicaciones externas.

+0

Existen varias implementaciones de VBScript disponibles en Google, p. Ej. "[Comprimir y descomprimir archivos con Windows Shell (XP, Vista, 2003 y 2008) y VBScript] (http://www.naterice.com/blog/template_permalink.asp?id=64)". No he probado estos pero lo más probable es que solo 'zip', no se comprimen. – samjudson

+1

¿Cuál es la distinción que está dibujando entre zip y compress? – Cheeso

+1

Puede 'comprimir' archivos en un solo archivo sin comprimirlos, al igual que 'tar' en Unix. Esto le permite distribuir los archivos como un paquete, pero no reduce su tamaño de espacio en disco. – samjudson

Respuesta

28

Hay métodos de VBA para zip y unzip usando también las ventanas integradas en compresión, lo que debería dar una idea de cómo funciona el sistema. Puede ser capaz de construir estos métodos en un lenguaje de scripting de su elección.

El principio básico es que dentro de Windows puede tratar un archivo zip como un directorio y copiarlo dentro y fuera de él. Entonces, para crear un nuevo archivo comprimido, simplemente crea un archivo con la extensión .zip que tiene el encabezado correcto para un archivo zip vacío. Luego, lo cierra y le dice a Windows que desea copiar archivos como si fuera otro directorio.

Descomprimir es más fácil: solo trátelo como un directorio.

En caso de que las páginas web se pierden de nuevo, aquí están algunos de los fragmentos de código relevantes:

postal

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

Advertencia: las secuencias de comandos publicadas dependen del comportamiento dependiente de la implementación del shell de Windows y, por ejemplo, pueden romperse fácilmente cuando el software de compresión de terceros cambia los verbos OLE predeterminados para los archivos ZIP. Además, los objetos COM zipfldr.dll * no * están documentados o son compatibles con este uso por MS. –

+0

Faux, los verbos OLE en archivos zip no interfieren con los scripts proporcionados anteriormente. No apoyar (o documentar) no significa automáticamente que los Estados miembros van a romperlo. Podrían, pero luego podrían documentarlo también. – wqw

+0

Los enlaces están muertos – beerwin

1

Hay ejecutables zip y descomprimir (así como una carga de embarcaciones de otras aplicaciones útiles) en el paquete UnxUtils disponible en SourceForge (http://sourceforge.net/projects/unxutils). Cópielos en una ubicación de su PATH, como 'c: \ windows', y podrá incluirlos en sus scripts.

Esta no es la solución perfecta (o la que usted solicitó) sino un trabajo decente.

+2

Parece que el proyecto UnxUtils ya no se mantiene (nada nuevo desde 2007). El [proyecto GNUWin32] (http://gnuwin32.sourceforge.net/) tiene versiones más recientes de herramientas GNU en Windows. Incluye compilaciones de zip/descomprimir [InfoZip] (http://www.info-zip.org/). Pero es mejor y más seguro crear directamente InfoZip [desde su propia fuente] (http://sourceforge.net/projects/infozip/files/). – dolmen

24

Sí, esto puede ser escrito con VBScript. Por ejemplo, el código siguiente se puede crear una postal de un directorio:

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 

También puede encontrar http://www.naterice.com/blog/template_permalink.asp?id=64 útil ya que incluye una implementación completa Descomprimir/Zip en VBScript.

Si realiza una comprobación de tamaño cada 500 ms en lugar de contar un elemento, funciona mejor para archivos de gran tamaño. Win 7 escribe el archivo al instante a pesar de que no ha terminado la compresión:

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

funciona muy bien para grandes cantidades de archivos de registro.

+0

¿Funciona esto en Vista? He estado encontrando algunos problemas y estoy a punto de afirmar que Vista es el culpable. – Icode4food

5

Solo por cuestión de claridad: GZip no es un algoritmo de MS solo como lo sugiere Guy Starbuck en su comentario de agosto. El GZipStream en System.IO.Compression utiliza el algoritmo Deflate, al igual que la biblioteca zlib, y muchas otras herramientas zip. Esa clase es totalmente interoperable con utilidades de Unix como gzip.

La clase GZipStream no se puede escribir desde la línea de comandos o VBScript, para producir archivos ZIP, por lo que solo no sería una respuesta a la solicitud del póster original.

La biblioteca gratuita DotNetZip lee y produce archivos zip, y se puede escribir desde VBScript o Powershell. También incluye herramientas de línea de comandos para producir y leer/extraer archivos zip.

Aquí hay un código de 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.") 

Aquí hay algo de código para 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"); 

En un .bat o .cmd, se puede utilizar el zipit.exe o unzip.exe herramientas. Por ejemplo:

zipit NewZip.zip -s "This is string content for an entry" Readme.txt src 
1

para crear un archivo comprimido se puede utilizar la utilidad MAKECAB.EXE

+0

No son archivos ZIP, pero aún así, podría ser útil, ¡gracias! – travis

+1

-1 - Los CAB no son ZIP – user66001

2

Here'a mi intento de resumir capacidades incorporadas en Windows para la compresión y descompresión - How can I compress (/ zip) and uncompress (/ unzip) files and folders with batch file without using any external tools?

con una pocas soluciones dadas que deberían funcionar en casi todas las máquinas de Windows.

Por lo que respecta a la Shell.Application y WSH prefería la jscript ya que permite que un archivo por lotes/JScript híbrido (con .bat extensión) que no requieren temp files.I've poner capacidades descomprimir y de la cremallera en un archivo más algunas características más.

Cuestiones relacionadas