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

10

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

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

yarone
источник

Ответы:

14
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 файлами на стандартный вывод (в терминале), поэтому, если вы хотите создать файл списка, вы можете 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 ))сделать unzip подсчитать файлы, извлечь число из выходных данных (конечно, есть более простой способ извлечь только число, но я знаю, sedчто я использовал его - см . комментарий @ muru для более простого способа, который может быть быстрее со многими файлами) и проверить, меньше ли это 15, и если это
  • echo "$z" затем напечатайте имя файла
  • | tee small-zip-list также распечатать вывод в новый файл, а также в терминал
Занна
источник
Спасибо @Zanna, я пытался запустить скрипт fires, и он всегда показывает все имена файлов .zip в папке, даже если я уменьшаю число с 15 до чего-то меньшего, он показывает все файлы .zip в папке.
yarone
@ yarone очень жаль, я пропустил пробел! Я исправил это сейчас, я надеюсь, пожалуйста, попробуйте еще раз
Zanna
6
Может быть немного проще в использовании zipinfo: zipinfo -1 foo.zip | wc -lилиzipinfo -t foo.zip | awk '{print $1}'
Муру
@ yarone очень приветствуется! : D
Zanna
+1 Использовал одно из следующего: awk, sed, grep;)
Nonny Moose
9

Поздний вариант python, использующий python's' 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)
    

    Печатает файл (+ путь), только если число перечисленных элементов меньше, чем n.

Якоб Влейм
источник
1
Python? zipfile !
Муру
@Muru еще раз спасибо, это имеет значение :)
Jacob Vlijm
9

Использование 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, то будет напечатано имя файла.

маргаритка
источник
5

В 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
Сергей Колодяжный
источник
0
for z in *.zip; do if (( $(unzip -Z1 "$z" | wc -l) < 15 )); then echo "$z"; fi;done
user1048382
источник
небольшое изменение в коде @ zanna "$ (unzip -Z1" $ z "| wc -l)"
user1048382
0

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

$ for f in *.zip; do \
  a=($(zipinfo -t "$f")); \
  (($a > 15)) && echo $f; done
bac0n
источник