¿Puede comprimir un archivo desde el símbolo del sistema utilizando SOLO la capacidad integrada de Windows para comprimir archivos?

111

Tengo un archivo por lotes que genera un archivo de texto. Pensé que sería bueno si pudiera cerrarlo también.

Esto se usará en un entorno no controlado, por lo que no puedo hacer suposiciones sobre la presencia de productos de software de terceros como 7-Zip , etc. Esto necesita usar la capacidad ahora incorporada de Windows para comprimir archivos.

Aaron Bush
fuente
1
¿Se puede utilizar la secuencia de comandos Powershell o WSH? esa podría ser la única forma de usar el manejo zip integrado de Windows desde la línea de comandos. de lo contrario, como señala Molly, necesita una herramienta de terceros.
quack quijote
1
entonces le envías a alguien un archivo por lotes y no puedes enviarle un pequeño gzip.exe estáticamente vinculado?
akira
La pregunta del OP es excelente (a pesar de la extraña acusación de @quackquixote). Dado que Windows proporciona esto como un solo clic en SendTo, debería haber un comando que se pueda usar en un archivo BAT. Por lo tanto, es una buena pregunta incluso si la respuesta es No y uno tiene que recurrir (ridículamente) al uso de una herramienta de terceros que puede o no ser equivalente.
Jon Coombs
Este es un enlace de Tomás que tiene un script bien escrito para comprimir el contenido de una carpeta. Para que funcione, simplemente copie el script en un archivo por lotes y ejecútelo especificando la carpeta que se va a comprimir (fuente). No es necesario mencionar el directorio de destino, ya que está predeterminado en el script para Escritorio ("% USERPROFILE% \ Desktop")
Abhijeet
3
Lo más simple sería, en un indicador de cmd: powershell.exe Compress-Archive file-to-zip.txt zippedfile.zip(también funciona con la carpeta)
ThomasGuenet

Respuestas:

85

Aquí hay una solución de archivo por lotes (una variación de mi otra respuesta) que comprimirá un archivo llamado c:\ue_english.txty lo colocará C:\someArchive.zip:

set FILETOZIP=c:\ue_english.txt

set TEMPDIR=C:\temp738
rmdir %TEMPDIR%
mkdir %TEMPDIR%
xcopy /s %FILETOZIP% %TEMPDIR%

echo Set objArgs = WScript.Arguments > _zipIt.vbs
echo InputFolder = objArgs(0) >> _zipIt.vbs
echo ZipFile = objArgs(1) >> _zipIt.vbs
echo CreateObject("Scripting.FileSystemObject").CreateTextFile(ZipFile, True).Write "PK" ^& Chr(5) ^& Chr(6) ^& String(18, vbNullChar) >> _zipIt.vbs
echo Set objShell = CreateObject("Shell.Application") >> _zipIt.vbs
echo Set source = objShell.NameSpace(InputFolder).Items >> _zipIt.vbs
echo objShell.NameSpace(ZipFile).CopyHere(source) >> _zipIt.vbs
echo wScript.Sleep 2000 >> _zipIt.vbs

CScript  _zipIt.vbs  %TEMPDIR%  C:\someArchive.zip

pause

Se requiere acceso de escritura al padre de la carpeta almacenada en TEMPDIR. Como este no suele ser el caso, la raíz de la unidad C TEMPDIRpuede tener que cambiarse.

También se requiere acceso de escritura para la carpeta en la que se .batencuentra el script (ya que genera un archivo allí).

Además, tenga en cuenta que la extensión del archivo comprimido debe ser .zip. Los intentos de usar otra extensión pueden provocar un error de script. En su lugar, genere el .ziparchivo y cámbiele el nombre.

Peter Mortensen
fuente
3
@quack estaba aguantando con la esperanza de algún comando oscuro que no conocía. Puedo ver cómo podrías encontrar que un requisito difícil si uno no existe no significaba sacar a nadie.
Aaron Bush
@PeterMortensen: Puede o no ser interesante ver cuánto se simplifica esto con Powershell. Aquí hay un ejemplo de 5 líneas , pero también existe un write-zipcmdlet que se puede descargar desde Pscx .
Tamara Wijsman
Usé el zip.exe y cywin1.dll (3mb) para satisfacer el ZIP y el uso es una línea ... desde el propio zip de usar algún código de lote. Sé que puedo usar un php bancompile'd con argv y pasarle un archivo. Suena bien. "Un zip desde la línea de comandos de Windows" es una vieja película de ciencia ficción, ¿verdad?
erm3nda
¿Por qué tenemos que usar una carpeta temporal TEMPDIR? Creo que su intención es envolver el archivo FILETOZIPen una carpeta, ¿verdad?
Nam G VU
@ Peter Mortensen, sé que este es un hilo viejo, y esto es casi lo que estoy buscando. ¿Existe una opción para comprimir un archivo grande en fragmentos más pequeños?
JohnG
38

Que es posible comprimir archivos sin necesidad de instalar ningún software adicional (he probado). La solucion es:

Ejecute esto en una ventana de línea de comandos para crear un archivo ZIP llamado que C:\someArchive.zipcontenga todos los archivos en la carpeta C:\test3:

CScript  zip.vbs  C:\test3  C:\someArchive.zip

Donde el archivo zip.vbscontiene:

' Get command-line arguments.
Set objArgs = WScript.Arguments
Set FS = CreateObject("Scripting.FileSystemObject")
InputFolder = FS.GetAbsolutePathName(objArgs(0))
ZipFile = FS.GetAbsolutePathName(objArgs(1))

' Create an empty ZIP file.
CreateObject("Scripting.FileSystemObject").CreateTextFile(ZipFile, True).Write "PK" & Chr(5) & Chr(6) & String(18, vbNullChar)

Set objShell = CreateObject("Shell.Application")

Set source = objShell.NameSpace(InputFolder).Items

objShell.NameSpace(ZipFile).CopyHere(source)

' Required to let the ZIP command execute
' If this script randomly fails or the ZIP file is not complete,
' just increase to more than 2 seconds
wScript.Sleep 2000

No lo he probado para rutas y nombres de archivos que contienen espacios. Puede funcionar si las comillas se colocan alrededor de los parámetros de la línea de comando.


Cómo funciona: la funcionalidad zip incorporada en Windows (Windows XP y posterior) se expone a través de las interfaces COM desde el shell de Windows, explorer.exe, que es la parte "Shell.Application". Esta interfaz COM se puede usar desde un script VBScript porque dicho script puede acceder a los componentes COM. Para hacer que el script sea completamente autónomo, crea un archivo ZIP vacío para comenzar (también se podría crear un archivo ZIP vacío y copiarlo al sistema de destino junto con el script VBScript).

VBScript se ha instalado de manera predeterminada en cada versión de escritorio de Microsoft Windows desde Windows 98.

CScript.exees parte de Windows Script Host . Windows Script Host se distribuye e instala de manera predeterminada en Windows 98 y versiones posteriores de Windows. También se instala si está instalado Internet Explorer 5 (o una versión posterior).

Peter Mortensen
fuente
1
+1 Buena solución que "Just Run", pero elijo BAT por otras razones que no figuran en la lista. Entonces preferiría una solución BAT.
Aaron Bush
44
@ Aaron Bush: este script y el de Beaner proporcionan un comando que comprime un archivo en la línea de comando, utilizando las funciones integradas de Windows, según lo solicitado. puede agregar ese comando a un archivo por lotes como cualquier otro.
quack quijote
Tenga en cuenta que las rutas pasadas deben ser absolutas, no relativas. También tuve que usar las técnicas en la respuesta aquí: stackoverflow.com/q/1645843/99640
Chuck Wilbur
Las rutas deben ser absolutas y parece fallar al azar :(
kixorz
Esto debe seleccionarse como la respuesta.
The Duke Of Marshall שלום
12

Si está abierto a usar PowerShell , las capacidades zip están disponibles en .NET 2.0 (PowerShell es .NET). Aquí hay un ejemplo ( fuente ) de crédito para Mike Hodnick :

########################################################
# out-zip.ps1
#
# Usage:
#    To zip up some files:
#       ls c:\source\*.txt | out-zip c:\target\archive.zip $_
#
#    To zip up a folder:
#       gi c:\source | out-zip c:\target\archive.zip $_
########################################################

$path = $args[0]
$files = $input

if (-not $path.EndsWith('.zip')) {$path += '.zip'} 

if (-not (test-path $path)) { 
  set-content $path ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18)) 
} 

$ZipFile = (new-object -com shell.application).NameSpace($path) 
$files | foreach {$zipfile.CopyHere($_.fullname)}
Beaner
fuente
Esto es básicamente lo mismo que el código CScript en otras respuestas. No se utilizan características .NET (y .NET no tiene soporte ZIP de todos modos). Sospecho que esto también podría ser sensible al problema del tiempo.
Robert Schmidt
2
La clase .NET System.IO.Compression.ZipFile se agregó en la versión 4.5.
Gannet de hormigón el
7

Puede eliminar el riesgo de tiempo de espera durante la compresión al sondear la existencia de la ventana de diálogo de compresión. Este método también maneja la cancelación del usuario fuera de la ventana de compresión.

objShell.NameSpace(ZipFile).CopyHere(source)

' Wait for compression window to open
set scriptShell = CreateObject("Wscript.Shell")
Do While scriptShell.AppActivate("Compressing...") = FALSE   
   WScript.Sleep 500 ' Arbitrary polling delay
Loop  

' Wait for compression to complete before exiting script
Do While scriptShell.AppActivate("Compressing...") = TRUE   
   WScript.Sleep 500 ' Arbitrary polling delay
Loop
George Yockey
fuente
1
+1. Esos códigos tipo " .Sleep(whatever)" mono me enferman.
ivan_pozdeev
1
Si estoy ejecutando un vbs con la lógica anterior para esperar, ¿cómo se manejará esto si se inicia mediante una tarea programada (donde ningún usuario ha iniciado sesión físicamente)?
Wes
5

Si puede instalar las herramientas del Kit de recursos , encontrará una herramienta de línea de comandos llamada COMPRESS que puede crear archivos comprimidos como zip.

Microsoft (R) File Compression Utility  Version 5.00.2134.1
Copyright (C) Microsoft Corp. 1990-1999.  All rights reserved.

Compresses one or more files.

COMPRESS [-r] [-d] [-z] Source Destination
COMPRESS -r [-d] [-z] Source [Destination]

  -r            Rename compressed files.
  -d            Update compressed files only if out of date.
  -zx           LZX compression.
  -z            MS-ZIP compression.
  -zq[n]        Quantum compression and optional level
                (in range 1-7, default is 4).
  Source        Source file specification.  Wildcards may be used.
  Destination   Destination file | path specification.
                Destination may be a directory.
                If Source is multiple files and -r is not specified,
                Destination must be a directory.
cowgod
fuente
3
+1 Realmente no resuelve las cosas, pero aún es bueno saberlo.
Aaron Bush
3
'Keep script waiting until compression is done
Do Until objShell.NameSpace( ZipFile ).Items.Count = objShell.NameSpace( InputFolder ).Items.Count
    WScript.Sleep 200
Loop
Jiří Kočara
fuente
exactamente lo que estaba buscando ... pero me da un error "falta en el archivo Zip vacío"
Sonic Soul
Por alguna razón, esto nunca se incrementa, si imprimo objShell.NameSpace( ZipFile ).Items.Countdentro del bucle, siempre es 0 a pesar de que se crea el archivo zip y tiene el contenido esperado dentro ...
Thom Nichols
2

Múltiples archivos / directorios con código simplificado.

cscript zip.vbs target.zip sourceFile1 sourceDir2 ... sourceObjN

archivo zip.vbs

Set objArgs = WScript.Arguments
ZipFile = objArgs(0)

' Create empty ZIP file and open for adding
CreateObject("Scripting.FileSystemObject").CreateTextFile(ZipFile, True).Write "PK" & Chr(5) & Chr(6) & String(18, vbNullChar)
Set zip = CreateObject("Shell.Application").NameSpace(ZipFile)

' Add all files/directories to the .zip file
For i = 1 To objArgs.count-1
  zip.CopyHere(objArgs(i))
  WScript.Sleep 10000 'REQUIRED!! (Depending on file/dir size)
Next
Olc
fuente
2

Esta es una mutación de la respuesta aceptada. Hago un montón de tareas de automatización en hasta miles de archivos a la vez, por lo que no puedo dormir durante 2 segundos y no me importa. Obtuve la solución alternativa aquí , que también es similar a la respuesta de Jiří Kočara aquí .

Esto hará que la carpeta de destino se pinche cada 200 ms, que es aproximadamente tan rápido como Microsoft dice que busque actualizaciones de FS.

Set parameters = WScript.Arguments
Set FS = CreateObject("Scripting.FileSystemObject")
SourceDir = FS.GetAbsolutePathName(parameters(0))
ZipFile = FS.GetAbsolutePathName(parameters(1))
CreateObject("Scripting.FileSystemObject").CreateTextFile(ZipFile, True).Write "PK" & Chr(5) & Chr(6) & String(18, vbNullChar)
Set shell = CreateObject("Shell.Application")
Set source_objects = shell.NameSpace(SourceDir).Items
Set ZipDest = shell.NameSpace(ZipFile)
Count=ZipDest.Items().Count
shell.NameSpace(ZipFile).CopyHere(source_objects)
Do While Count = ZipDest.Items().Count
    wScript.Sleep 200
Loop
kayleeFrye_onDeck
fuente
1

Aquí está mi intento de resumir las ventanas de capacidades incorporadas para compresión y descompresión: https://stackoverflow.com/questions/28043589/how-can-i-compres-zip-and-uncopress-unzip-files-and-folders -with-batch-f

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

En lo que respecta a la aplicación shell.y WSH, preferí el jscript ya que permite un archivo híbrido por lotes / jscript (con extensión .bat) que no requiere archivos temporales. He puesto capacidades de descompresión y compresión en un archivo más algunas características más .

npocmaka
fuente
0

Si en Windows 8 o Windows Server 2012 tendrá PowerShell y .NET 4.5 para que pueda hacer esto:

zip.ps1 (uso :)-directory <directory to zip up> -name <zip name> :

param (
    [string]$directory,
    [string]$name
)

Add-Type -Assembly System.IO.Compression.FileSystem
[System.IO.Compression.ZipFile]::CreateFromDirectory($directory, $name, [System.IO.Compression.CompressionLevel]::Optimal, $false)

zip.bat (si necesita un ayudante para llamar a PowerShell por usted, el directorio es el primer argumento y el nombre zip segundo):

@Echo Off
powershell -ExecutionPolicy ByPass -Command "& '%~dpn0.ps1' -directory '%1' -name '%2'"
Hashbrown
fuente
0

Windows 10 build 17063 o posterior se incluye con tar.exe, que es capaz de trabajar con zip desde la línea de comandos.

tar.exe -xf archive.zip

o para crear un archivo

tar.exe -cf Test.zip Test
venimus
fuente
-5

La línea de comandos de Windows ahora proporciona el comando compacto que, por lo que puedo decir, es nativo de Windows. Eso debería cumplir con los requisitos solicitados a menos que me haya perdido algo.

usuario228211
fuente
99
compactexistía desde XP y es una herramienta para administrar la compresión NTFS
Der Hochstapler