Listar arquivos zip com menos de um número específico de arquivos

10

Eu tenho milhares de .ziparquivos em uma pasta. Desejo descobrir quais arquivos zip têm menos de 15 arquivos.

Sei que unzip -lpode listar o conteúdo dos arquivos zip, mas não sei como criar uma saída de arquivos zip com menos de 15 arquivos.

yarone
fonte

Respostas:

14
for z in *.zip; do if (( $(unzip -l "$z" | sed -nr '$ s/.* ([0-9]+) files?/\1/p') < 15 )); then echo "$z"; fi; done

Isso lista os .ziparquivos com menos de 15 arquivos para stdout (no terminal); portanto, se você deseja criar um arquivo de lista, pode teesair ou redirecionar. Aqui está mais facilmente, criando um arquivo de lista no final e imprimindo no terminal

for z in *.zip; do 
   if (( $(unzip -l "$z" | sed -nr '$ s/.* ([0-9]+) files?/\1/p') < 15 )); then 
      echo "$z"
   fi
done | tee small-zip-list

Notas

  • for z in *.ziploop sobre arquivos que terminam com .zipe fazem algo para cada um, representado pela variável zreferenciada com$z
  • if (( $(unzip -l "$z" | sed -nr '$ s/.* ([0-9]+) files?/\1/p') < 15 ))faça descompactar a contagem dos arquivos, extraia o número da saída (certamente há uma maneira mais organizada de extrair apenas o número, mas eu sei sedque eu o usei - veja o comentário do @ muru para uma maneira mais simples que pode ser mais rápida com muitos arquivos) e teste se tem menos de 15 e se é
  • echo "$z" depois imprima o nome do arquivo
  • | tee small-zip-list também imprime a saída em um novo arquivo, bem como no terminal
Zanna
fonte
Obrigado @Zanna, tentei executar o script fires e sempre mostra todos os nomes de arquivos .zip na pasta, mesmo que eu esteja diminuindo o número do formulário 15 para algo menor, ele mostra todos os arquivos .zip na pasta.
yarone
@yarone, desculpe, perdi um espaço! Eu fixo-lo esperança agora eu, por favor, tente novamente
Zanna
6
Pode ser um pouco mais fácil de usar zipinfo: zipinfo -1 foo.zip | wc -louzipinfo -t foo.zip | awk '{print $1}'
Muru
@yarone muito bem-vindo! : D
Zanna 28/02
+1 Usou um dos seguintes: awk, sed, grep;)
Nonny Moose
9

Uma opção python tardia, usando python's' zipfile(como sugerido por @muru, obrigado!)

#!/usr/bin/env python3
import os
import sys
from zipfile import ZipFile

dr = sys.argv[1]

for zp in [os.path.join(dr, f) for f in os.listdir(dr) if f.endswith(".zip")]:
    if len(ZipFile(zp, "r").namelist()) < int(sys.argv[2]):
        print(zp)

Como usar

  1. Copie o script em um arquivo vazio, salve-o como get_zips.py
  2. Execute-o com o diretório e o número (mínimo) desejado de arquivos dentro, por exemplo:

    python3 /path/to/get_zips.py /full/path/to/directory_with_zips 15
    

Explicação

O script:

  • lista .ziparquivos dentro de um diretório:

    for zp in [os.path.join(dr, f) for f in os.listdir(dr) if f.endswith(".zip")]:
  • Olha dentro do arquivo e conta o número de arquivos:

    if len(ZipFile(file, "r").namelist()) < n:
        print(file)

    Somente imprime o arquivo (caminho +) se o número de itens listados for menor n.

Jacob Vlijm
fonte
1
Pitão? zipfile !
muru
@muru obrigado novamente, que faz a diferença :)
Jacob Vlijm
9

Usando o awk :

for i in ~/path/to/your/folder/*.zip; do if (( $(unzip -l $i | awk 'END {print $(NF-1)}') < 15 )); then echo "$i"; fi; done

Ou também pode ser feito com script.

Criar script zip.sh

#!/bin/bash

for i in ~/path/to/your/folder/*.zip; do
    if (( $(unzip -l $i | awk 'END {print $(NF-1)}') < 15 )); then
        echo "$i"
    fi
done

Salve-o na pasta pessoal e torne-o executável chmod +x zip.she execute a partir do terminal./zip.sh

Aqui, if (( $(unzip -l $i | awk 'END {print $(NF-1)}') < 15 )),

  • unzip -l $i contará o número de arquivos do respectivo arquivo zip e de sua saída,

  • awk 'END {print $(NF-1)}' grep apenas esse número de contagem, se for menor que 15, ele imprimirá o nome do arquivo.

margarida
fonte
5

O Perl também possui um pacote para lidar com arquivos zip Archive::Zip,. O script abaixo usa arquivos zip como argumentos da linha de comando e fornece saída da linha de comando com o nome e a contagem de arquivos no arquivo morto.

#!/usr/bin/env perl
use strict;
use warnings;
use Archive::Zip;

foreach (@ARGV){
    my $fh = Archive::Zip::->new();
    if (my $error = $fh->read($_)){
        die "Read error:" . $_;
    }
    if($fh->numberOfMembers() < 15 ){
        printf("%s\t%d\n",$_,$fh->numberOfMembers());
    }
}

Execução de teste:

$ ./count_zip_contents.pl  *.zip                           
129804-findmac.py.zip   1
Re%3a_China_and_East_Asia_%5bHIS-1250-010_31616.201730%5d%3a_Team_up_for_East_Asian_History_class.zip   4
University_Formal_jpg&tif.zip   5
indicator-places-master.zip 4
lab 5.zip   8
Sergiy Kolodyazhnyy
fonte
0
for z in *.zip; do if (( $(unzip -Z1 "$z" | wc -l) < 15 )); then echo "$z"; fi;done
user1048382
fonte
uma pequena alteração no código de @ zanna "$ (descompacte -Z1" $ z "| wc -l)"
user1048382
0

Obtenha o número total de arquivos usando o zipinfo:

$ for f in *.zip; do \
  a=($(zipinfo -t "$f")); \
  (($a > 15)) && echo $f; done
bac0n
fonte