#!/bin/env python3 # FindCaseClash.py # Given an input file with a list of files from case senstive p4d # Output the dir and file clashses. # The input file should be the output of: # sort -f filelist | uniq -Di > filedups.txt # So all files are in case insensitive sort order # Python 2.7/3.3 compatibility. from __future__ import print_function import sys from os.path import basename, splitext from collections import defaultdict class ClashFinder: "Finds new directories in paths - seperate class for ease of testing" def __init__(self): self.dupCount = defaultdict(int) self.lpaths = defaultdict(list) def findCommonPartInd(self, parts1, parts2): # Returns index for common part i = 1 while i <= len(parts1): p1 = "/".join(parts1[:i]) p2 = "/".join(parts2[:i]) if p1 != p2: return i-1 i += 1 return 0 def checkCommonDirs(self, parts1, parts2): # We know parts aren't the same - just confirm equal lengths if len(parts1) != len(parts2): print("Problem: '%s' '%s'" % ("/".join(parts1), "/".join(parts2))) return ind = self.findCommonPartInd(parts1, parts2) if ind == 0 or ind == len(parts1): print("/".join(parts1)) print("/".join(parts2)) return # Want one more than common part p1 = "/".join(parts1[:ind+1]) p2 = "/".join(parts2[:ind+1]) self.dupCount[p1] += 1 self.dupCount[p2] += 1 self.lpaths[p1.lower()].append(p1) self.lpaths[p1.lower()].append(p2) # This method returns None if no new directory found, or the directory name def checkClash(self, paths): if len(paths) != 2: print("Error Not2: %s" % ",".join(paths)) return self.checkCommonDirs(paths[0][2:].split("/"), paths[1][2:].split("/")) def printClashes(self): seen = {} for k in self.lpaths.keys(): for j in self.lpaths[k]: if self.dupCount[j] == 1 and j not in seen: print("%s" % (j)) seen[j] = 1 elif j not in seen: print("%d %s/" % (self.dupCount[j], j)) seen[j] = 1 if __name__ == '__main__': cf = ClashFinder() with open(sys.argv[1]) as f: lastline = None paths = [] for line in f: line = line.rstrip() if line.lower() == lastline: paths.append(line) else: if paths: cf.checkClash(paths) lastline = line.lower() paths = [line] cf.printClashes()