Uit Hack42
| 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 | + | |
| + | For recent updates check [https://github.com/Hack42/RomanRotate Github] | ||
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.
