Como saber quanto espaço um zip não compactado terá

23

Dada uma lista (muito longa) de arquivos zip, como você pode saber o tamanho deles depois de descompactados?

Quora Feans
fonte

Respostas:

38

Você pode fazer isso usando o unzip -Zt zipnameque imprime um resumo diretamente sobre o conteúdo do arquivo, com tamanho total. Aqui está um exemplo em sua saída:

unzip -Zt a.zip
1 file, 14956 bytes uncompressed, 3524 bytes compressed:  76.4%

Em seguida, usando o awk, você pode extrair o número de bytes:

unzip -Zt a.zip | awk '{print $3}'
14956

Por fim, coloque-o em um loop for, como na resposta de Tom:

total=0
for file in *.zip; do # or whichever files you want
    (( total += $(unzip -Zt $file |awk '{ print $3 }') ))
done
echo $total
Bichoy
fonte
19

Se você digitar unzip -l <zipfile>, ele imprimirá uma lista de arquivos dentro do zip, com seus tamanhos não compactados, e o tamanho total não compactado de todos eles.

Esta é uma saída legível por humanos, mas você pode obter um número legível por máquina usando unzip -l <zipfile> | tail -n1 | awk '{ print $1 }'.

Para obter um tamanho total:

total=0
for file in *.zip; do # or whichever files you want
    (( total += $(unzip -l $file | tail -n1 | awk '{ print $1 }') ))
done
echo $total
Tom Hunt
fonte
15

unzip -llista o tamanho de cada arquivo e imprime uma linha final com sua soma. Assim, você pode percorrer os arquivos zip e adicionar a saída deunzip -l "$zip" | awk 'END {print $1}' ou de unzip -Zt "$zip" | awk 'END {print $3}'. Para um loop de shell, unzip -Ztpode ser um pouco mais rápido:

total=0
for z in *.zip; do
  set $(unzip -Zt -- "$z")
  total=$((total + $3))
done

Isso informa apenas o tamanho total dos arquivos. Cada arquivo possui uma pequena sobrecarga: o espaço para armazenar seu nome, o espaço para armazenar alguns de seus metadados e possivelmente um pouco de espaço não utilizado, porque a maioria dos sistemas de arquivos aloca arquivos em blocos. Em sistemas de arquivos típicos, a sobrecarga pode chegar a alguns kilobytes. Não é exatamente previsível, porque a sobrecarga depende do tamanho do arquivo, da estrutura do diretório (devido à sobrecarga do diretório) e dos recursos do sistema de arquivos para mesclar vários arquivos pequenos no mesmo bloco.

Se a maioria dos arquivos tiver mais do que alguns kilobytes, não se preocupe. Mas se os arquivos forem muito pequenos, convém levar em consideração a sobrecarga. Mais uma vez, a sobrecarga depende do sistema de arquivos. No ext4, cada arquivo preenche um bloco completo (4kB por padrão na maioria dos sistemas). O script a seguir aproxima o tamanho total, arredondando cada arquivo até 4kB e adicionando o comprimento do nome do arquivo mais alguns bytes.

for z in *.zip; do
  unzip -l -- "$z"
done | awk '
    $2 ~ /^[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]$/ {total += ($1+4095)/4096*4096 + length($0)}
    END {print total}
'
Gilles 'SO- parar de ser mau'
fonte
+1 por mencionar arquivos pequenos e o fato de os sistemas de arquivos não compactarem arquivos pequenos da mesma maneira que um zip. AFAIK, nenhum sistema de arquivos convencional no win / OSX / Linux / BSD (ou seja, aqueles que você pode recomendar que alguém use para / e / home em sua área de trabalho ou servidor) possui um pequeno pacote de arquivos como opção. O Reiserfs tinha a opção de fazer isso (e os restos de arquivos maiores), mas não é mantido. Eu não tinha pensado em nomes de arquivos massivamente longos , no entanto. Boa pegada.
22615 Peter Cordes
Você também pode adicionar uma constante de 256B ou 512B por arquivo, pois esse é o tamanho de um inode (no XFS). Porém, acho que o ext4 ainda aloca estaticamente inodes, portanto, o espaço não usado para inodes não pode conter outros dados. (É por isso que ext4 tem um baixo número tão elevado de inodes livres ( df -i), em comparação com XFS que pode alocar dinamicamente o máximo de espaço para inodes como ele precisa.)
Peter Cordes
1

Olha ma, sem loops!

Aqui está outra solução, que pode ser um pouco mais rápida, porque não usa loops, mas ainda chega à mesma resposta.

unzip -l \*.zip|awk 'BEGIN{total=0}/        [0-9]+ files/{total=total+$1;}END{print "total bytes: "total}'

A parte "BEGIN {total = 0}" não é estritamente necessária.

WormFood
fonte