-
Notifications
You must be signed in to change notification settings - Fork 10
/
fillingGaps.py
96 lines (72 loc) · 3.46 KB
/
fillingGaps.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
'''
Chapter 10 Organizing Files
Filling in the Gaps
Write a program that finds all files with a given prefix, such as spam001.txt,
spam002.txt, and so on, in a single folder and locates any gaps in the
numbering (such as if there is a spam001.txt and spam003.txt but no spam002.txt).
Have the program rename all the later files to close this gap.
'''
# fillingGaps.py - Renames all files with the given prefix in a dir,
# so there are no gaps in the numbering sequence. It checks where the
# sequence start and pads all files to the same length of leading zeros
# Usage: python fillingGaps.py rootDir filenamePrefix
import sys, os, re, shutil
from pathlib import Path
from operator import itemgetter
import logging
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
def findMatchingFiles(rootDir, filenamePrefix):
''' Matches the files in the rootDir to the given prefix and
returns a list with the Path, integer literal, the integer literal
as int and the suffix of the filename.
'''
pattern = re.compile(r'(' + filenamePrefix + r')(\d+)(.*)')
gapFileList = []
for filename in os.listdir(rootDir):
mo = pattern.match(filename)
if mo is not None:
intLiteral = mo.group(2)
fileSuffix = mo.group(3)
gapFileList.append([Path(rootDir).resolve() / filename, intLiteral, int(intLiteral), fileSuffix])
return gapFileList
def getLongestIntLiteral(sortedFileList):
''' Returns the size of the longest integer literal e.g. 0002 --> 4
TODO: Maybe there is a shorter pythonic version
'''
lengthIntLiteral = 0
for sortedFile in sortedFileList:
if len(sortedFile[1]) > lengthIntLiteral:
lengthIntLiteral = len(sortedFile[1])
return lengthIntLiteral
def renameFiles(sortedFileList, lengthIntLiteral, filenamePrefix, gapAt=0):
''' Loops through every file in the list. If the number in
the file name is not the next in the sequence or hasn't the right
amount of leading zeros renames it.
'''
# Find out where the sequence begins
start = sortedFileList[0][2]
if(gapAt is not 0):
sortedFileList = sortedFileList[gapAt-sortedFileList[0][2]:]
start=gapAt-1+start
for i, gapFile in enumerate(sortedFileList, start=start):
''' Check if the index is not the same as the number OR
the length of the integer literal is not the length of the longest
integer literal in the list
'''
if (i is not gapFile[2] or len(gapFile[1]) is not lengthIntLiteral):
# i:0{lengthNumber} pads the new number to the length of the longest int literal
src = gapFile[0]
dest = Path(os.path.dirname(gapFile[0])) / f'{filenamePrefix}{i:0{lengthIntLiteral}}{gapFile[3]}'
logging.info(f'renaming {src.name} to {dest.name}')
shutil.move(src, dest)
if __name__ == "__main__":
if(len(sys.argv) == 3):
rootDir = Path(sys.argv[1])
filenamePrefix = sys.argv[2]
gapFileList = findMatchingFiles(rootDir, filenamePrefix)
# Sort the list of files by the number
sortedFileList = sorted(gapFileList, key=itemgetter(int(2)))
lengthIntLiteral = getLongestIntLiteral(sortedFileList)
renameFiles(sortedFileList, lengthIntLiteral, filenamePrefix)
else:
print('Usage: python fillingGaps.py rootDir filenamePrefix')