Lista de archivos zip que tienen menos de un número específico de archivos

10

Tengo miles de .ziparchivos en una carpeta. Deseo encontrar qué archivos zip tienen menos de 15 archivos.

Sé que unzip -lpuede enumerar el contenido de los archivos zip, pero no sé cómo crear una salida de archivos zip que tengan menos de 15 archivos.

yarone
fuente

Respuestas:

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

Esto enumera los .ziparchivos con menos de 15 archivos para stdout (en el terminal), por lo que si desea crear un archivo de lista, puede teesalir o redirigir. Aquí es más legible, crear un archivo de lista al final e imprimir en el 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 *.ziprecorrer los archivos que terminan con .zipy hacer algo a cada uno, representado por la variable zreferenciada con$z
  • if (( $(unzip -l "$z" | sed -nr '$ s/.* ([0-9]+) files?/\1/p') < 15 ))haga que descomprimir cuente los archivos, extraiga el número de la salida (seguramente hay una forma más ordenada de extraer solo el número, pero sé que sedlo he usado; vea el comentario de @ muru para una forma más simple que puede ser más rápida con muchos archivos) y compruebe si es inferior a 15 y si es
  • echo "$z" luego imprima el nombre del archivo
  • | tee small-zip-list También imprima la salida a un nuevo archivo, así como en el terminal
Zanna
fuente
Gracias @Zanna Intenté ejecutar el script de incendios y siempre muestra todos los nombres de archivo .zip en la carpeta, incluso si estoy disminuyendo el número de forma 15 a algo más pequeño, muestra todos los archivos .zip en la carpeta.
yarone
@yarone lo siento mucho, me perdí un espacio! Lo he arreglado ahora, espero, inténtalo de nuevo
Zanna
66
Puede ser un poco más fácil de usar zipinfo: zipinfo -1 foo.zip | wc -lozipinfo -t foo.zip | awk '{print $1}'
muru
@yarone muy bienvenido! : D
Zanna
+1 Usó uno de los siguientes: awk, sed, grep;)
Nonny Moose
9

Una opción de python tardía, usando python's zipfile, (como lo sugirió @muru, ¡gracias!)

#!/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)

Cómo utilizar

  1. Copie el script en un archivo vacío, guárdelo como get_zips.py
  2. Ejecútelo con el directorio y el número deseado (mínimo) de archivos dentro, por ejemplo:

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

Explicación

La secuencia de comandos:

  • enumera .ziparchivos dentro de un directorio:

    for zp in [os.path.join(dr, f) for f in os.listdir(dr) if f.endswith(".zip")]:
  • Mira dentro del archivo y cuenta la cantidad de archivos:

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

    Solo imprime el archivo (+ ruta) si el número de elementos de la lista es menor n.

Jacob Vlijm
fuente
1
¿Pitón? zipfile !
muru
@muru gracias de nuevo, eso hace la diferencia :)
Jacob Vlijm
9

Usando 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

O también se puede hacer con script.

Crear 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

Guárdelo en la carpeta de inicio y hágalo ejecutable con chmod +x zip.shy ejecute desde la terminal./zip.sh

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

  • unzip -l $i contará el número de archivos del archivo zip respectivo y de su salida,

  • awk 'END {print $(NF-1)}' grep ese número de recuento solamente, si es menor que 15, imprimirá el nombre del archivo.

margarita
fuente
5

Perl también tiene un paquete para el manejo de archivos zip, Archive::Zip. El siguiente script toma archivos zip como argumentos de línea de comandos y proporciona una salida de línea de comandos con el nombre y el recuento de archivos dentro del archivo.

#!/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());
    }
}

Prueba de funcionamiento:

$ ./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
fuente
0
for z in *.zip; do if (( $(unzip -Z1 "$z" | wc -l) < 15 )); then echo "$z"; fi;done
usuario1048382
fuente
un cambio menor al código de @ zanna "$ (descomprimir -Z1" $ z "| wc -l)"
usuario1048382
0

Obtenga el número total de archivos usando zipinfo:

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