#!/usr/bin/env python3

import os
import re

faulty_name = re.compile(r'(?P<base_name>.*?)(?P<timestamps>(-[0-9]{8}){2,})$')
generic_name = re.compile(r'(?P<base_name>.*?)(?P<timestamps>(-[0-9]{8})*?)(?P<last_timestamp>-[0-9]{8})$')

def candidate_names(name, candidates=None):
    if not candidates:
        candidates = []
    n = generic_name.match(name)
    if n:
        candidates.append(n.group('base_name') + n.group('last_timestamp'))
        return candidate_names(n.group('base_name') + n.group('timestamps'), candidates)
    return candidates

def find_faulty(root_path='/var/log'):
    """For each file in directory root_path and sub-directories,
    erase empty file which name ends with several timestamps,
    attempt to rename file which name ends with several timestamps keeping only one timestamp,
    if this is not possible due to conflicting name, do nothing
    """
    print('Purge log files with non-conventional names')
    erased = []
    renamed = []
    not_renamed = []
    for d in os.walk(root_path):
        for f in d[2]:
            if faulty_name.match(f):
                file_path = os.path.join(d[0], f)
                if os.stat(file_path).st_size == 0:
                    os.unlink(file_path)
                    erased.append(file_path)
                else:
                    is_renamed = False
                    for candidate_name in candidate_names(f):
                       new_name = os.path.join(d[0], candidate_name)
                       if not (os.path.exists(new_name) or os.path.exists(new_name + '.gz')):
                           os.rename(file_path, new_name)
                           renamed.append((file_path, new_name))
                           is_renamed = True
                           break
                    if not is_renamed:
                        not_renamed.append(file_path)
    print('Erased files:\n\t', '\n\t '.join(erased))
    print('Renamed files:\n\t', '\n\t '.join(['{} to {}'.format(*r) for r in renamed]))
    print('Untouched files:\n\t', '\n\t '.join(not_renamed))

find_faulty()
