У меня есть тысячи .zip
файлы в одной папке. Я хочу найти, какие zip-файлы имеют меньше чем 15 файлов в них.
Я знаю это unzip -l
может перечислить содержание zip-файлов, но я не знаю, как создать вывод zip-файлов, которые имеют меньше чем 15 файлов.
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
также вывод печати в новый файл, а также в терминале Последняя опция 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)
get_zips.py
Выполните его с каталогом и желаемым (минимальным) количеством файлов внутри, например:
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
.
Используя 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 затем, это распечатает имя файла.
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
for z in *.zip; do if (( $(unzip -Z1 "$z" | wc -l) < 15 )); then echo "$z"; fi;done
Получить общее количество файлов с помощью zipinfo:
$ for f in *.zip; do \
a=($(zipinfo -t "$f")); \
(($a > 15)) && echo $f; done