Uit Hack42
k |
|||
(2 tussenliggende versies door dezelfde gebruiker niet weergegeven) | |||
Regel 17: | Regel 17: | ||
Was an incentive enough to create this bit of python code which provides Roman numbered log rotation | Was an incentive enough to create this bit of python code which provides Roman numbered log rotation | ||
+ | |||
+ | For recent updates check [https://github.com/Hack42/RomanRotate Github] | ||
+ | |||
<pre> | <pre> | ||
Regel 36: | Regel 39: | ||
""" | """ | ||
assert(isinstance(input, int)), "expected integer, got %s" % type(input) | assert(isinstance(input, int)), "expected integer, got %s" % type(input) | ||
− | assert( | + | assert(-1 < input < 4000), "Argument must be between 0 and 3999" |
ints = (1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1) | ints = (1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1) | ||
nums = ('M', 'CM', 'D', 'CD','C', 'XC','L','XL','X','IX','V','IV','I') | nums = ('M', 'CM', 'D', 'CD','C', 'XC','L','XL','X','IX','V','IV','I') | ||
Regel 52: | Regel 55: | ||
""" | """ | ||
assert(isinstance(input, basestring)), "expected string, got %s" % type(input) | assert(isinstance(input, basestring)), "expected string, got %s" % type(input) | ||
− | assert(re.match(r'^[MDCLXVI] | + | assert(re.match(r'^[MDCLXVI]*$', input)), "not a valid roman numeral: %s" % input |
input = input.upper() | input = input.upper() | ||
nums = ['M', 'D', 'C', 'L', 'X', 'V', 'I'] | nums = ['M', 'D', 'C', 'L', 'X', 'V', 'I'] | ||
Regel 74: | Regel 77: | ||
def keys(value): | def keys(value): | ||
− | if re.match(r'([MDCLXVI] | + | if re.match(r'([MDCLXVI]*)', value): |
debug("Roman: %s, Decimal %s" % (value, rom2dec(value))) | debug("Roman: %s, Decimal %s" % (value, rom2dec(value))) | ||
return((rom2dec(value), value)) | return((rom2dec(value), value)) | ||
else: | else: | ||
return((value, dec2rom(value))) | return((value, dec2rom(value))) | ||
+ | |||
+ | def usage(): | ||
+ | print """ | ||
+ | Usage: %s [-v] [-h] [-d delimiter] [-l] [-t] file [file] | ||
+ | Description: Performs logrotation with roman numbering. | ||
+ | |||
+ | -v Verbose, show debug output | ||
+ | -h Help, show this usage | ||
+ | -d delimiter delimiter between filename and roman extension | ||
+ | deault; '.' | ||
+ | -l List the rotates files ordered by number | ||
+ | -t Reverse rotation or list | ||
+ | Attention: this might cause loss of data in the most recent logfile! | ||
+ | |||
+ | file the filename without numbers, i.e. "logfile.log" or "/path/to/logfile.log" | ||
+ | """ % sys.argv[0] | ||
class FileList(set): | class FileList(set): | ||
− | def __init__(self, directory, filename): | + | def __init__(self, directory, filename, delimiter): |
if(directory!=''): | if(directory!=''): | ||
self._directory = directory | self._directory = directory | ||
Regel 87: | Regel 106: | ||
self._directory = '.' | self._directory = '.' | ||
self._filename = filename | self._filename = filename | ||
+ | self._delimiter = delimiter | ||
debug('Getting files for %s in directory %s' % (self._filename, self._directory)) | debug('Getting files for %s in directory %s' % (self._filename, self._directory)) | ||
for file in os.listdir(self._directory): | for file in os.listdir(self._directory): | ||
try: | try: | ||
− | parts = re.split(r'(%s | + | parts = re.split(r'(%s)([%s]*)([MCXDVIL]*)' % (self._filename, self._delimiter), file) |
− | if | + | if parts[1] == self._filename: |
− | debug('Adding: %s' % file) | + | debug('Adding: %s %s' % (file, parts)) |
− | self.add(keys(parts[ | + | self.add(keys(parts[3]) + (parts[1], file,)) |
except Exception, err: | except Exception, err: | ||
+ | debug(err) | ||
debug('Ignoring: %s' % file) | debug('Ignoring: %s' % file) | ||
pass | pass | ||
Regel 106: | Regel 127: | ||
listOnly = False | listOnly = False | ||
reverse = False | reverse = False | ||
− | optlist, args = getopt.getopt(sys.argv[1:], ' | + | delimiter = '.' |
+ | optlist, args = getopt.getopt(sys.argv[1:], 'lthvd:') | ||
for option, value in optlist: | for option, value in optlist: | ||
if(option == '-v'): | if(option == '-v'): | ||
Regel 114: | Regel 136: | ||
if(option == '-t'): | if(option == '-t'): | ||
reverse = True | reverse = True | ||
+ | if(option == '-d'): | ||
+ | delimiter = optarg | ||
if(option == '-h'): | if(option == '-h'): | ||
usage() | usage() | ||
+ | exit | ||
debug('Verbose is on') | debug('Verbose is on') | ||
debug('Filenames: %s' % args) | debug('Filenames: %s' % args) | ||
for item in args: | for item in args: | ||
debug('Processing: %s' % item) | debug('Processing: %s' % item) | ||
− | myList = FileList(os.path.dirname(item), os.path.basename(item)) | + | myList = FileList(os.path.dirname(item), os.path.basename(item), delimiter) |
if listOnly: | if listOnly: | ||
for file in myList.sort(reverse): | for file in myList.sort(reverse): | ||
Regel 126: | Regel 151: | ||
else: | else: | ||
for file in myList.sort(not reverse): | for file in myList.sort(not reverse): | ||
− | + | number = dec2rom(file[0] - (+1 if reverse else -1)) | |
− | + | filename = file[2] + (('.' + number) if number != '' else '') | |
− | + | debug('renaming %s to %s.' % (file[3], "%s" % filename)) | |
− | + | os.rename(file[3], "%s" % filename) | |
− | |||
− | |||
</pre> | </pre> | ||
− | The code could be cleaned up a little and the usage method is missing but rumour has it it's already running in production (which is, of course, the best testing environment). | + | <s>The code could be cleaned up a little and the usage method is missing but rumour has it it's already running in production (which is, of course, the best testing environment).</s> |
+ | |||
+ | First revision; added Usage function and optional delimiter character. Solved bug 1; The core file (without any numbering) is now included in the renaming. |
Huidige versie van 10 sep 2013 om 00:06
Project: RomanRotate | |
---|---|
Naam | RomanRotate |
Door | Stoneshop, Dvanzuijlekom, WitchDoc |
Status | Afgerond |
Madskillz | Madness |
Doel / Omschrijving | |
Roman numbering log rotation | |
Alle Projecten - Project Toevoegen |
This;
18:34 <@dvanzuijlekom> zo kwam ik een tijd geleden een machine tegen waar iemand handmatig een soort logrotate had ingeregeld 18:35 <@dvanzuijlekom> resultaat: logfile.log, logfile.log.1, logfile.log.1.1 logfile.log.1.1.1 logfile.log.1.1.1.1....logfile.log.1.1.1.1.1.1.1.1.1.1.1.1.1 18:39 <@Stoneshop> initieel wat romeinse invloeden, maar niet op de juiste manier voortgezet 18:42 <@dvanzuijlekom> oh wauw, dat zou best gaaf zijn eigenlijk
Was an incentive enough to create this bit of python code which provides Roman numbered log rotation
For recent updates check Github
#!/usr/bin/env python import sys import os import re import getopt def debug(argv): global verbose if verbose: print >>sys.stderr, "DBG: %s" % argv def dec2rom(input): """ Convert a decimal to Roman numerals. """ assert(isinstance(input, int)), "expected integer, got %s" % type(input) assert(-1 < input < 4000), "Argument must be between 0 and 3999" ints = (1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1) nums = ('M', 'CM', 'D', 'CD','C', 'XC','L','XL','X','IX','V','IV','I') result = "" for i in range(len(ints)): count = int(input / ints[i]) result += nums[i] * count input -= ints[i] * count return result def rom2dec(input): """ Convert a roman numeral to a decimal. """ assert(isinstance(input, basestring)), "expected string, got %s" % type(input) assert(re.match(r'^[MDCLXVI]*$', input)), "not a valid roman numeral: %s" % input input = input.upper() nums = ['M', 'D', 'C', 'L', 'X', 'V', 'I'] ints = [1000, 500, 100, 50, 10, 5, 1] retValue = 0 for i in range(len(input)): value = ints[nums.index(input[i])] # If the next place holds a larger number, this value is negative. try: if ints[nums.index(input[i +1])] > value: value *= -1 except IndexError: # there is no next place. pass retValue += value # Easiest test for validity... if dec2rom(retValue) == input: return retValue else: raise ValueError, 'input is not a valid roman numeral: %s' % input def keys(value): if re.match(r'([MDCLXVI]*)', value): debug("Roman: %s, Decimal %s" % (value, rom2dec(value))) return((rom2dec(value), value)) else: return((value, dec2rom(value))) def usage(): print """ Usage: %s [-v] [-h] [-d delimiter] [-l] [-t] file [file] Description: Performs logrotation with roman numbering. -v Verbose, show debug output -h Help, show this usage -d delimiter delimiter between filename and roman extension deault; '.' -l List the rotates files ordered by number -t Reverse rotation or list Attention: this might cause loss of data in the most recent logfile! file the filename without numbers, i.e. "logfile.log" or "/path/to/logfile.log" """ % sys.argv[0] class FileList(set): def __init__(self, directory, filename, delimiter): if(directory!=''): self._directory = directory else: self._directory = '.' self._filename = filename self._delimiter = delimiter debug('Getting files for %s in directory %s' % (self._filename, self._directory)) for file in os.listdir(self._directory): try: parts = re.split(r'(%s)([%s]*)([MCXDVIL]*)' % (self._filename, self._delimiter), file) if parts[1] == self._filename: debug('Adding: %s %s' % (file, parts)) self.add(keys(parts[3]) + (parts[1], file,)) except Exception, err: debug(err) debug('Ignoring: %s' % file) pass def sort(self, reverse=False): return sorted(self, key=lambda file: file[0], reverse=reverse) if __name__ == "__main__": global verbose verbose = False listOnly = False reverse = False delimiter = '.' optlist, args = getopt.getopt(sys.argv[1:], 'lthvd:') for option, value in optlist: if(option == '-v'): verbose = True if(option == '-l'): listOnly = True if(option == '-t'): reverse = True if(option == '-d'): delimiter = optarg if(option == '-h'): usage() exit debug('Verbose is on') debug('Filenames: %s' % args) for item in args: debug('Processing: %s' % item) myList = FileList(os.path.dirname(item), os.path.basename(item), delimiter) if listOnly: for file in myList.sort(reverse): print file[3] else: for file in myList.sort(not reverse): number = dec2rom(file[0] - (+1 if reverse else -1)) filename = file[2] + (('.' + number) if number != '' else '') debug('renaming %s to %s.' % (file[3], "%s" % filename)) os.rename(file[3], "%s" % filename)
The code could be cleaned up a little and the usage method is missing but rumour has it it's already running in production (which is, of course, the best testing environment).
First revision; added Usage function and optional delimiter character. Solved bug 1; The core file (without any numbering) is now included in the renaming.