Zip-файлы списка, которые имеют меньше, чем определенное количество файлов

У меня есть тысячи .zip файлы в одной папке. Я хочу найти, какие zip-файлы имеют меньше чем 15 файлов в них.

Я знаю это unzip -l может перечислить содержание zip-файлов, но я не знаю, как создать вывод zip-файлов, которые имеют меньше чем 15 файлов.

10
задан 28 February 2017 в 01:52

6 ответов

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

Это перечисляет эти .zip файлы меньше чем с 15 файлами к stdout (в терминале), поэтому если Вы хотите создать файл списка, Вы можете tee или перенаправление. Здесь это больше четко, создавая файл списка в конце, а также печатая в Примечаниях терминала

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

  • for z in *.zip цикл по файлам, заканчивающимся .zip, и сделайте что-то каждому, представленному переменной z ссылаемый с $z
  • if (( $(unzip -l "$z" | sed -nr '$ s/.* ([0-9]+) files?/\1/p') < 15 )) делают, разархивировали, считают файлы, извлекают число из вывода (существует, конечно, более опрятный способ извлечь только число, но я знаю sed, таким образом, я использовал его - видят комментарий @muru для более простого пути, который может быть быстрее со многими файлами), и протестируйте, является ли это меньше чем 15, и если это
  • echo "$z", затем печатают имя файла
  • | tee small-zip-list также вывод печати в новый файл, а также в терминале
14
ответ дан 23 November 2019 в 04:15

Последняя опция Python, с помощью python zipfile, (как предложено @muru, Спасибо!)

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

Как использовать

  1. Скопируйте сценарий в пустой файл, сохраните его как get_zips.py
  2. Выполните его с каталогом и желаемым (минимальным) количеством файлов внутри, например:

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

Объяснение

Сценарий:

  • списки .zip файлы в каталоге:

    for zp in [os.path.join(dr, f) for f in os.listdir(dr) if f.endswith(".zip")]:
    
  • Взгляды в файле и количествах количество файлов:

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

    Только печатает файл (+path), если количество перечисленных объектов меньше затем n.

9
ответ дан 23 November 2019 в 04:15

Используя 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

Или это может быть также сделано со сценарием.

Создайте сценарий 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

Сохраните его в домашней папке и Сделайте его исполняемым файлом с chmod +x zip.sh и выполненный от терминала ./zip.sh

Здесь, if (( $(unzip -l $i | awk 'END {print $(NF-1)}') < 15 )),

  • unzip -l $i это будет считать количество файлов из соответствующего zip-файла и от его вывода,

  • awk 'END {print $(NF-1)}' grep, которые считают число только, если это - меньше чем 15 затем, это распечатает имя файла.

9
ответ дан 23 November 2019 в 04:15

Perl также имеет пакет для обработки архивов zip, Archive::Zip. Сценарий ниже zip-файлов взятий как параметры командной строки и предоставляет выводу командной строки имя и количество файлов в архиве.

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

Тестовый прогон:

$ ./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
5
ответ дан 23 November 2019 в 04:15
for z in *.zip; do if (( $(unzip -Z1 "$z" | wc -l) < 15 )); then echo "$z"; fi;done
0
ответ дан 27 February 2020 в 08:37

Получить общее количество файлов с помощью zipinfo:

$ for f in *.zip; do \
  a=($(zipinfo -t "$f")); \
  (($a > 15)) && echo $f; done
0
ответ дан 27 February 2020 в 13:04

Другие вопросы по тегам:

Похожие вопросы: