Como "extrair" um arquivo zip?

52

Eu extraí um arquivo zip em uma pasta não vazia. O arquivo zip tem muitos arquivos e uma hierarquia profunda, que é mesclada com a árvore existente do diretório de destino. Como posso remover os arquivos e diretórios que foram criados ao descompactar sem destruir os arquivos e diretórios que já estavam lá? Claro, eu ainda tenho o arquivo zip que eu mesclei, então as informações estão lá.

    
por mafp 14.02.2013 / 00:24

5 respostas

27

A jjlin é o caminho a seguir. Eu só quero adicionar algumas opções para diretórios:

  • Exclua todos os arquivos extraídos, sem diretórios :

    unzip -lqq file.zip | gawk -F"  " '{print $NF;}' |
      while IFS= read -r n; do rm "$n"; done
    
  • Exclua arquivos extraídos e apenas diretórios vazios

    unzip -lqq file.zip | gawk -F"  " '{print $NF;}' |
      while IFS= read -r n; do rm "$n"; done; rmdir *
    

    Sem opções, rmdir exclui somente os diretórios vazios, ele deixará arquivos e pastas não vazias sozinhos, para que você possa executá-lo com segurança em * .

  • Exclua tudo extraído, mas solicite uma confirmação antes de cada exclusão:

    unzip -lqq file.zip | gawk -F"  " '{print $NF;}' |
      while IFS= read -r n; do rm -ri "$n"; done; rmdir *
    

    O sinalizador -i fará com que rm seja solicitado antes de cada remoção, você pode escolher Sim ou Não.

  • Exclua tudo extraído, diretórios incluídos:

    unzip -lqq file.zip | gawk -F"  " '{print $NF;}' |
      while IFS= read -r n; do rm -rf "$n"; done
    
por 14.02.2013 / 01:44
28

Você pode usar unzip -lqq <filename.zip> para listar o conteúdo do arquivo zip; Isso incluirá algumas informações estranhas que você precisará filtrar. Aqui está um comando que funciona para mim:

unzip -lqq file.zip | awk '{print $4;}' | xargs rm -rf

O comando awk extrai apenas os nomes dos arquivos e diretórios. Em seguida, o resultado é passado para xargs para excluir tudo. Eu sugiro fazer um teste do comando (ou seja, omitindo a parte xargs rm -rf ) primeiro para ter certeza de que os resultados estão corretos.

O comando acima terá problemas ao lidar com caminhos que tenham espaço em branco. Esta versão (mais complicada) deve corrigir isso:

unzip -lqq file.zip | awk '{$1=$2=$3=""; sub(/ */, "", $0); printf "%s%s", $0, "
unzip -lqq file.zip | awk '{print $4;}' | xargs rm -rf
"}' | xargs -0 rm -rf
    
por 14.02.2013 / 00:46
11

Com a opção -Z1 , o unzip listará exatamente um arquivo por linha (e nada mais).

Dessa forma, você pode usar

unzip -Z1 | xargs -I {} rm '{}'

para excluir todos os arquivos extraídos do arquivo zip.

O comando

unzip -Z1 | xargs -I {} rm -rf '{}'

também irá deletar diretórios, mas você precisa ter cuidado. Se os diretórios já existirem antes de extrair o arquivo zip, todos os arquivos pré-existentes nesses diretórios serão excluídos também.

Se você for re-extrair o arquivo zip de qualquer maneira, existe outra abordagem que é garantida para lidar com nomes de arquivos estranhos.

Primeiro, extraia o arquivo zip onde você originalmente queria extraí-lo:

unzip file.zip -d elsewhere

Agora, mude para o diretório em que você extraiu os arquivos por engano e execute o seguinte comando:

find elsewhere -type f -printf "%P
find -type d -exec rmdir -p {} \; 2> /dev/null
" | xargs -0 -I {} rm '{}'
  • -type f só encontra arquivos (sem diretórios).

  • %Pelsewhere/ é o caminho relativo (sem -0 ), seguido por um caractere nulo.

  • -type d faz xargs separar linhas por caracteres nulos. Isso é mais confiável, já que, em teoria, os nomes dos arquivos podem conter caracteres de nova linha.

Para lidar com diretórios restantes, você pode executar o comando:

unzip -Z1 | xargs -I {} rm '{}'
  • -exec rmdir -p {} \; só encontra diretórios.

  • rmdir -p {} executa {} para cada diretório encontrado.

    -p é o diretório que foi encontrado, e a opção 2> /dev/null faz o rmdir remover seus diretórios pai vazios também.

  • %code% suprime as mensagens de erro que surgirão ao tentar excluir diretórios não vazios ou excluídos anteriormente.

Páginas de manual relacionadas:

por 14.02.2013 / 01:57
2

Aqui está uma solução ainda mais fácil e segura (eu acho)

zip -m getmeoutofhere.zip 'unzip -lqq myoriginalzipfile.zip'
rm getmeoutofhere.zip

O que isso está fazendo: O comando de descompactação backquoted produzirá uma lista do que estava em seu arquivo original.

zip -m irá então usar essa lista para adicionar add that each para getmeoutofhere.zip e removê-lo do diretório original (então, teoricamente, deve ser indential para myoriginalfile.zip.

A desvantagem é que o unzip -lqq produzirá texto, datas, horas, tamanho de arquivo, etc. extras. Isso fará com que zip -m produza mensagens de erro, mas isso não deve afetar (a menos que você tem o caso improvável de um arquivo com o mesmo nome).

Por favor, note que isto não removerá nenhum diretório que tenha sido criado durante a descompactação original.

    
por 19.02.2013 / 23:02
1

Se você extraiu os arquivos de forma que o registro de data e hora da modificação no archive não seja preservado nas cópias extraídas (mas os arquivos extraídos têm seu horário de modificação usual), o caminho certo para atacar é através do tempo de modificação. Todos os arquivos extraídos têm um registro de data e hora de modificação mais recente do que o arquivo existente modificado mais recentemente nesse diretório.

Aqui está uma situação simples.

Suponha que nenhum dos arquivos existentes no diretório atual foi tocado por pelo menos 24 horas. Qualquer coisa que tenha sido modificada nas últimas 24 horas é, portanto, lixo do arquivo zip.

$ find . -mtime -1 -print0 | xargs -0 rm

Isso também encontrará alguns diretórios, mas rm os deixará em paz. Eles podem ser tratados em uma segunda passagem:

$ find . -mtime 1 -type d -print 0 | xargs -0 rmdir

Todos os diretórios que foram modificados recentemente foram modificados pelo zip. Se rmdir os remover com sucesso, isso significa que eles estão vazios. Os diretórios vazios que foram tocados pelo zip provavelmente foram criados por ele: ou seja, vieram do archive. Não podemos ter 100% de certeza. É possível que o trabalho de descompactação coloque alguns arquivos em um diretório existente que estava vazio.

Se a granularidade de 24 horas de find não for boa o suficiente para o trabalho, porque os arquivos na árvore foram modificados muito recentemente, considerarei algo simples: suponha que o trabalho de descompactar não tenha colocado nada em subdiretórios existentes. Ou seja, tudo o que foi descompactado é um arquivo no nível superior ou um novo subdiretório que não estava lá antes, que, portanto, contém apenas material do zip. Então:

# list directory in descending order of modification time
$ ls -1t > filelist  # descending order of modification time

Agora abrimos filelist em um editor de texto e determinamos a primeira entrada na lista que não veio do zip. Excluímos essa entrada e todo o resto depois dela. O que resta são os arquivos e diretórios que vieram do zip. Primeiro inspecionamos visualmente problemas como espaços nos nomes e ocorrências de cotações que precisam ser escapadas. Podemos então adicionar aspas em torno de tudo, se necessário: O seguinte pressupõe que você use o Vim:

:%s/.*/"&"/

Em seguida, junte tudo em uma grande linha:

:%j

Agora insira rm -rf na frente dele:

Irm - rf<ESC>

Execute a linha sob o cursor como um comando shell:

!!sh<Enter>

Definitivamente, eu não iria automatizar os passos desta tarefa, devido ao risco de apagar arquivos que já estavam lá, ou estragar devido a problemas com nomes de arquivos.

Se você estiver indo para a rota óbvia de obter uma lista dos caminhos no zip, capture-a em um arquivo, examine-a com muito cuidado e a transforme em uma remoção depois de fazer qualquer edição necessária.

    
por 14.02.2013 / 05:36

Tags