zip zip zip

This commit is contained in:
Geoffrey Frogeye 2020-03-12 17:56:10 +01:00
parent a6755863dd
commit c8aaa78f59
5 changed files with 175 additions and 33 deletions

View file

@ -56,8 +56,8 @@ set geometry(main) 1920x1012+0+18
set geometry(state) normal
set geometry(topwidth) 1920
set geometry(topheight) 225
set geometry(pwsash0) "969 1"
set geometry(pwsash1) "1454 1"
set geometry(botwidth) 1202
set geometry(pwsash0) "931 1"
set geometry(pwsash1) "971 1"
set geometry(botwidth) 951
set geometry(botheight) 782
set permviews {}

View file

@ -7,6 +7,7 @@ sudo pacman -S etckeeper --needed
sudo etckeeper commit "install-arch script: begin"
# Install yay
# TODO Use yay-bin
sudo pacman -S base-devel --needed
if ! pacman -Q yay &> /dev/null
then

View file

@ -3,16 +3,18 @@
import os
import re
import typing
import datetime
import PIL.ExifTags
import PIL.Image
import progressbar
EXTENSION_PATTERN = re.compile(r'\.JPE?G', re.I)
COMMON_PATTERN = re.compile(r'(IMG|DSC[NF]?|100|P10)_?\d+', re.I)
COMMON_PATTERN = re.compile(r'(IMG|DSC[NF]?|100|P10|f|t)_?\d+', re.I)
EXIF_TAG_NAME = 'DateTimeOriginal'
EXIF_TAG_ID = list(PIL.ExifTags.TAGS.keys())[list(
PIL.ExifTags.TAGS.values()).index(EXIF_TAG_NAME)]
EXIF_DATE_FORMAT = '%Y:%m:%d %H:%M:%S'
def get_pictures(directory: str = ".", skip_renamed: bool = True) \
@ -41,7 +43,10 @@ def main() -> None:
exif_data = img._getexif()
if exif_data and EXIF_TAG_ID in exif_data:
date_raw = exif_data[EXIF_TAG_ID]
# print(date_raw, full_path)
date = datetime.datetime.strptime(date_raw, EXIF_DATE_FORMAT)
new_name = date.isoformat().replace(':', '-') + '.jpg' # For NTFS
print(full_path, new_name)
os.rename(full_path, new_name) # TODO FOLDER
img.close()

View file

@ -83,7 +83,7 @@ echo "Finding packages to install"
# i A || i B: will try A for each installer, then B for each installer
# Package managers (install first)
i yay
i yay-bin
i python-pip python3-pip pip3
# TODO Install first and recharge installers
@ -107,7 +107,7 @@ i tmux # Terminal multiplexer
i bash-completion # Shell completions
i fzf # Fancy file finder
i highlight # Syntax highlighter (TODO No termux)
i powerline-go # Nice prompt (potential problem: requires go-pie)
i powerline-go-bin powerline-go # Nice prompt (potential problem: requires go-pie)
i zsh # Shell
# TODO Arch only for the following but not a problem
@ -135,6 +135,7 @@ i socat # Multi-purpose relay
i rsync # Remote file-copying tool
i speedtest-cli # Network speed benchmarker (TODO No termux)
i bind-tools dnsutils # DNS queryier
i whois # Domain name queryier
# Archives utilities
i unzip # Unarchive ZIP files
@ -203,6 +204,7 @@ then
i man # Documentation
i strace # Tracer
i ctags universal-ctags exuberant-ctags # Tags generator
i perf # Allow verifying performance of software
# C/C++
i cmake # C++ Build system
@ -250,6 +252,12 @@ then
i inkscape # Vector image converter
i optipng # Optimize PNG files
i jpegtran libjpeg-turbo # Compress JPEG files
i libreoffice-fresh # Office suite
i hunspell-en_GB # Spell checker British english
i hunspell-en_US # Spell checker American english
# i libreoffice-extension-grammalecte-fr # Spell checker French
i libreoffice-extension-languagetool # Complimentary spell checker various
# TODO The last two can't cohabit
fi
if $INSTALL_IMAGE

View file

@ -2,33 +2,161 @@
import os
import subprocess
import sys
import logging
import magic
import typing
import coloredlogs
import enum
for root, dirs, files in os.walk("."):
for name in files:
base, ext = os.path.splitext(name)
if name.endswith(".zip"):
cmd = ["unzip"]
elif name.endswith(".7z"):
cmd = ["7z", "e"]
elif name.endswith(".rar"):
cmd = ["unrar", "x"]
elif name.endswith('.tar'):
cmd = ["tar", "xf"]
elif name.endswith('.tar.gz'):
cmd = ["tar", "xzf"]
elif name.endswith('.tar.xz'):
cmd = ["tar", "xJf"]
# TODO Able to ignore extensions everywhere
class ArchiveType():
suffix: str = ''
dest_suffix: str = ''
mime: typing.Optional[str] = None
header: typing.Optional[bytes] = None
extract_cmd: typing.Optional[typing.List[str]] = None
single_file = False
append_dest = False
def __init__(self) -> None:
self.log = logging.getLogger(self.__class__.__name__)
def dest_name(self, archive: str) -> str:
return archive[:-len(self.suffix)] + self.dest_suffix
def fits(self, name_lower: str, mime: str, header: bytes) -> bool:
if not name_lower.endswith(self.suffix):
return False
if self.mime is not None and mime != self.mime:
return False
if self.header is not None and not header.startswith(self.header):
return False
return True
def _get_cmd(self, archive: str, dest: str) -> typing.List[str]:
assert self.extract_cmd
cmd = self.extract_cmd + [archive]
if self.append_dest:
cmd.append(dest)
return cmd
def extract(self, archive: str, dest: str) -> None:
cmd = self._get_cmd(archive, dest)
if not self.single_file:
os.mkdir(dest)
self.log.info("Extracting '%s' into '%s'", archive, dest)
self.log.debug("%s", cmd)
if self.single_file:
r = subprocess.run(cmd)
else:
continue
filepath = os.path.join(root, name)
dirpath = os.path.join(root, base)
print(filepath)
os.mkdir(dirpath)
cmd.append(os.path.realpath(filepath))
r = subprocess.run(cmd, cwd=dirpath)
r = subprocess.run(cmd, cwd=dest)
r.check_returncode()
if self.single_file:
assert os.path.isfile(dest)
os.unlink(archive)
os.unlink(filepath)
extract_fun: typing.Optional[typing.Callable[[str, str], None]] = None
class ArchiveZip(ArchiveType):
suffix = '.zip'
mime = 'application/zip'
extract_cmd = ['unzip']
class Archive7z(ArchiveType):
suffix = '.7z'
mime = 'application/x-7z-compressed'
extract_cmd = ['7z', 'x']
class ArchiveRar(ArchiveType):
suffix = '.rar'
mime = 'application/x-rar'
extract_cmd = ['unrar', 'x']
class ArchiveTar(ArchiveType):
suffix = '.tar'
mime = 'application/x-tar'
extract_cmd = ['tar', '--extract', '--file']
class ArchiveTarGz(ArchiveType):
suffix = '.tar.gz'
mime = 'application/gzip'
extract_cmd = ['tar', '--extract', '--gzip', '--file']
class ArchiveTarXz(ArchiveType):
suffix = '.tar.xz'
mime = 'application/x-xz'
extract_cmd = ['tar', '--extract', '--xz', '--file']
class ArchiveGzip(ArchiveType):
suffix = '.gz'
mime = 'application/gzip'
single_file = True
extract_cmd = ['gunzip']
class TreeExtractor():
ARCHIVE_TYPES: typing.List[ArchiveType] = [
ArchiveZip(),
Archive7z(),
ArchiveRar(),
ArchiveTar(),
ArchiveTarGz(),
ArchiveTarXz(),
ArchiveGzip(),
]
def __init__(self) -> None:
self.log = logging.getLogger('TreeExtractor')
self.extensions = set()
for archive_type in self.ARCHIVE_TYPES:
suffixes = archive_type.suffix.split('.')
self.extensions.add('.' + suffixes[-1])
def extract_tree(self, directory: str = '.') -> None:
for root, dirs, files in os.walk(directory):
real_root = os.path.realpath(root)
for name in files:
self.log.debug("Handling '%s' '%s'", real_root, name)
# Initial filtering with extensions
extension = os.path.splitext(name)[1].lower()
if extension not in self.extensions:
self.log.debug("Extension not matched: %s", name)
continue
name_lower = name.lower()
filepath = os.path.join(real_root, name)
with open(filepath, 'rb') as filedesc:
header = filedesc.read(1024)
mime = magic.from_buffer(header, mime=True)
archive_type = None
for archtyp in self.ARCHIVE_TYPES:
if archtyp.fits(name_lower, mime, header):
archive_type = archtyp
break
if not archive_type:
self.log.debug("Not matched: %s", filepath)
continue
dest_name = archive_type.dest_name(name)
dest = os.path.join(real_root, dest_name)
try:
archive_type.extract(filepath, dest)
except BaseException as e:
# TODO Parameters stop on error
self.log.error(e, exc_info=True)
if os.path.isdir(dest):
self.extract_tree(dest)
def main(self) -> None:
directory = sys.argv[1] if len(sys.argv) > 1 else '.'
self.extract_tree(directory)
if __name__ == '__main__':
coloredlogs.install(level='DEBUG', fmt='%(levelname)s %(message)s')
TreeExtractor().main()