Você pode compactar um arquivo a partir do prompt de comando usando APENAS o recurso interno do Windows para compactar arquivos?

96

Eu tenho um arquivo em lotes que gera um arquivo de texto. Eu pensei que seria legal se eu pudesse fechar também.

Isso será usado em um ambiente não controlado, por isso não posso fazer suposições sobre a presença de produtos de software de terceiros, como 7-Zip , etc. Isso precisa usar o recurso agora integrado do Windows para compactar arquivos.

Aaron Bush
fonte
1
você pode utilizar scripts Powershell ou WSH? essa pode ser a única maneira de usar o zip interno do Windows a partir da linha de comando. Caso contrário, como Molly salienta, você precisa de uma ferramenta de terceiros.
quack quixote
1
então você envia alguém um arquivo de lote e você não pode enviar-lhe alguns minúsculos gzip.exe vinculados estaticamente?
akira
A pergunta do OP é excelente (apesar da estranha acusação doquququixote). Como o Windows fornece isso como um único clique em SendTo, deveria para ser um comando utilizável em um arquivo BAT. Portanto, é uma boa pergunta, mesmo que a resposta seja Não e a pessoa precise (ridiculamente) recorrer ao uso de uma ferramenta de terceiros que pode ou não ser equivalente.
Jon Coombs
Isto é ligação por Tomas tem um script bem escrito para zipar o conteúdo de uma pasta. Para fazê-lo funcionar basta copiar o script em um arquivo de lote e executá-lo especificando a pasta a ser compactada (fonte). Não é necessário mencionar o diretório de destino, pois ele é padronizado no script para Desktop ("% USERPROFILE% \ Desktop")
Abhijeet
2
O mais simples seria, em um prompt de cmd: powershell.exe Compress-Archive file-to-zip.txt zippedfile.zip (funciona também com pasta)
ThomasGuenet

Respostas:

83

Aqui está uma solução de todos os arquivos em lote (uma variação da minha outra resposta) que irá zipar um arquivo chamado c:\ue_english.txt e colocá-lo em 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

O acesso de gravação é necessário para o pai da pasta armazenada em TEMPDIR. Como isso geralmente não é o caso da raiz da unidade C TEMPDIR pode ter que ser mudado.

O acesso de gravação também é necessário para a pasta .bat script está em (como ele gera um arquivo lá).

Além disso, observe que a extensão do arquivo compactado deve ser .zip. Tentativas de usar outra extensão podem resultar em um erro de script. Em vez disso, gere o .zip arquivo e renomeá-lo.

Peter Mortensen
fonte
3
@quack eu estava segurando na esperança de algum comando obscuro que eu não conhecia. Eu posso ver como você pode achar que um requisito difícil, se não existe, não significa colocar ninguém para fora.
Aaron Bush
@ PeterMortensen: Pode ou não ser interessante ver o quanto isso é simplificado com o Powershell. Aqui está um exemplo de 5 linhas , mas também existe um write-zip cmdlet que pode ser baixado do Pscx .
Tom Wijsman
Eu usei o zip.exe e cywin1.dll (3mb) para satisfazer o ZIP e uso é uma linha ... do próprio zip de usar algum código de lote. Eu sei que pode usar um php bancompile'd com argv e passar um arquivo para ele. Soa legal. "Um zip da linha de comando do windows" é um antigo filme de ficção científica, certo?
erm3nda
Por que temos que usar uma pasta temporária TEMPDIR? Eu acho que sua intenção é embrulhar o arquivo FILETOZIP por uma pasta certo?
Nam G VU
@ Peter Mortensen, eu sei que este é um tópico antigo, e isso é quase o que estou procurando. Existe uma opção para compactar um arquivo grande em partes menores?
JohnG
36

isto é possível zipar arquivos sem a instalação de qualquer software (eu testei). A solução é:

Execute isto em uma janela de linha de comando para criar um arquivo zip nomeado C:\someArchive.zip contendo todos os arquivos na pasta C:\test3:

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

Onde arquivo zip.vbs contém:

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

'Create 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

Eu não testei caminhos e nomes de arquivos contendo espaços. Pode funcionar se aspas são colocados em torno dos parâmetros da linha de comando.


Como funciona: a funcionalidade integrada de zip no Windows (Windows XP e posterior?) É exposta através COM interfaces do shell do Windows , explorer.exe - que é a parte "Shell.Application". Essa interface COM pode ser usada de um VBScript roteiro porque esse script pode acessar os componentes COM. Para tornar o script totalmente autocontido, cria um arquivo ZIP vazio para começar (também é possível criar um arquivo ZIP vazio e copiá-lo para o sistema de destino junto com o script VBScript).

O VBScript foi instalado por padrão em todos os desktops lançamento do Microsoft Windows desde o Windows 98.

CScript.exe faz parte do Windows Script Host. O Windows Script Host é distribuído e instalado por padrão no Windows 98 e versões posteriores do Windows. Ele também é instalado se o Internet Explorer 5 (ou uma versão posterior) estiver instalado.

Peter Mortensen
fonte
1
1 Boa solução que "Just Run" funcionará, mas eu escolho a BAT por vários outros motivos não listados. Então, eu preferiria uma solução BAT.
Aaron Bush
4
@Aaron Bush: este script e o Beaner fornecem um comando que fecha um arquivo na linha de comando, usando as funções do windows builtin, conforme solicitado. você pode adicionar esse comando a um arquivo de lote como qualquer outro.
quack quixote
Note que os caminhos passados ​​devem ser absolutos, não relativos. Eu também tive que usar as técnicas na resposta aqui: stackoverflow.com/q/1645843/99640
Chuck Wilbur
Caminhos tem que ser absoluto e parece falhar aleatoriamente :(
kixorz
Isso deve ser selecionado como a resposta.
The Duke Of Marshall שלום
12

Se você está aberto a usar PowerShell , os recursos zip estão disponíveis no .NET 2.0 (PowerShell é .NET). Aqui está um exemplo ( fonte ) 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
fonte
Isso é basicamente a mesma coisa que o código CScript em outras respostas. Nenhum recurso .NET é usado (e o .NET não tem suporte a ZIP de qualquer maneira). Eu suspeito que isso também seja sensível à questão do tempo.
Robert Schmidt
2
A classe .NET System.IO.Compression.ZipFile foi adicionada na versão 4.5.
Concrete Gannet
7

Você pode eliminar o risco de tempo limite durante a compactação pesquisando a existência da janela de diálogo de compactação. Esse método também manipula o usuário cancelando a janela de compactação.

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
fonte
1
+1. Aqueles código estilo macaco " .Sleep(whatever) " me deixa doente.
ivan_pozdeev
1
Se eu estiver executando um vbs com a lógica acima para espera, como isso será tratado se for iniciado por meio de uma tarefa agendada (na qual nenhum usuário está logado fisicamente).
Wes
4

Se você conseguir instalar o Ferramentas do Kit de Recursos , você encontrará uma ferramenta de linha de comando chamada COMPRESS que pode criar arquivos compactados como o 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
fonte
2
+1 realmente não resolve as coisas, mas ainda é bom saber.
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
fonte
exatamente o que eu estava procurando .. mas me dá um erro "faltando no arquivo Zip vazio"
Sonic Soul
Por alguma razão isso nunca aumenta, se eu imprimir objShell.NameSpace( ZipFile ).Items.Count dentro do loop, é sempre 0 mesmo que o arquivo zip seja criado e tenha o conteúdo esperado dentro ...
Thom Nichols
2

Vários arquivos / diretórios com código simplificado.

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

arquivo 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
fonte
2

Esta é uma mutação da resposta aceita. Eu faço uma tonelada de tarefas de automação em milhares de arquivos por vez, então eu não posso apenas dormir por 2 segundos e não me importar com isso. Eu peguei a solução alternativa Aqui , que também é semelhante à resposta de Jiří Kočara Aqui .

Isso fará com que a pasta de destino seja pingada a cada 200 ms, o que é aproximadamente o mais rápido que a Microsoft diz para verificar se há atualizações do 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
fonte
1

Aqui está minha tentativa de resumir as capacidades internas das janelas para compressão e descompressão - https://stackoverflow.com/questions/28043589/how-can-i-compres-zip-and-uncopress-unzip-files-and-folders-with-batch-f

com algumas soluções dadas que devem funcionar em quase todas as máquinas windows.

No que diz respeito à shell.application e WSH eu preferia o jscript como ele permite um arquivo híbrido em lote / jscript (com extensão .bat) que não requer arquivos temporários.Eu coloquei os recursos de descompactação e zip em um arquivo e mais alguns recursos adicionais.

npocmaka
fonte
0

Se no Windows 8 ou no Windows Server 2012 você terá o PowerShell e o .NET 4.5, você pode fazer isso:

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 (se você precisar de um ajudante para chamar o PowerShell para você, o diretório será o primeiro argumento e o nome do zip será o segundo):

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

A linha de comando do Windows agora fornece o comando compact que, até onde eu sei, é nativo do Windows. Isso deve atender aos requisitos solicitados, a menos que eu tenha perdido alguma coisa.

user228211
fonte
8
compact existia desde o XP e é uma ferramenta para gerenciar a compactação NTFS
Der Hochstapler