Edit File by line
/home/barbar84/public_h.../wp-conte.../plugins/sujqvwi/ExeBy/smexe_ro.../lib64/python2....
File: filecmp.py
"""Utilities for comparing files and directories.
[0] Fix | Delete
[1] Fix | Delete
Classes:
[2] Fix | Delete
dircmp
[3] Fix | Delete
[4] Fix | Delete
Functions:
[5] Fix | Delete
cmp(f1, f2, shallow=1) -> int
[6] Fix | Delete
cmpfiles(a, b, common) -> ([], [], [])
[7] Fix | Delete
[8] Fix | Delete
"""
[9] Fix | Delete
[10] Fix | Delete
import os
[11] Fix | Delete
import stat
[12] Fix | Delete
from itertools import ifilter, ifilterfalse, imap, izip
[13] Fix | Delete
[14] Fix | Delete
__all__ = ["cmp","dircmp","cmpfiles"]
[15] Fix | Delete
[16] Fix | Delete
_cache = {}
[17] Fix | Delete
BUFSIZE=8*1024
[18] Fix | Delete
[19] Fix | Delete
def cmp(f1, f2, shallow=1):
[20] Fix | Delete
"""Compare two files.
[21] Fix | Delete
[22] Fix | Delete
Arguments:
[23] Fix | Delete
[24] Fix | Delete
f1 -- First file name
[25] Fix | Delete
[26] Fix | Delete
f2 -- Second file name
[27] Fix | Delete
[28] Fix | Delete
shallow -- Just check stat signature (do not read the files).
[29] Fix | Delete
defaults to 1.
[30] Fix | Delete
[31] Fix | Delete
Return value:
[32] Fix | Delete
[33] Fix | Delete
True if the files are the same, False otherwise.
[34] Fix | Delete
[35] Fix | Delete
This function uses a cache for past comparisons and the results,
[36] Fix | Delete
with a cache invalidation mechanism relying on stale signatures.
[37] Fix | Delete
[38] Fix | Delete
"""
[39] Fix | Delete
[40] Fix | Delete
s1 = _sig(os.stat(f1))
[41] Fix | Delete
s2 = _sig(os.stat(f2))
[42] Fix | Delete
if s1[0] != stat.S_IFREG or s2[0] != stat.S_IFREG:
[43] Fix | Delete
return False
[44] Fix | Delete
if shallow and s1 == s2:
[45] Fix | Delete
return True
[46] Fix | Delete
if s1[1] != s2[1]:
[47] Fix | Delete
return False
[48] Fix | Delete
[49] Fix | Delete
outcome = _cache.get((f1, f2, s1, s2))
[50] Fix | Delete
if outcome is None:
[51] Fix | Delete
outcome = _do_cmp(f1, f2)
[52] Fix | Delete
if len(_cache) > 100: # limit the maximum size of the cache
[53] Fix | Delete
_cache.clear()
[54] Fix | Delete
_cache[f1, f2, s1, s2] = outcome
[55] Fix | Delete
return outcome
[56] Fix | Delete
[57] Fix | Delete
def _sig(st):
[58] Fix | Delete
return (stat.S_IFMT(st.st_mode),
[59] Fix | Delete
st.st_size,
[60] Fix | Delete
st.st_mtime)
[61] Fix | Delete
[62] Fix | Delete
def _do_cmp(f1, f2):
[63] Fix | Delete
bufsize = BUFSIZE
[64] Fix | Delete
with open(f1, 'rb') as fp1, open(f2, 'rb') as fp2:
[65] Fix | Delete
while True:
[66] Fix | Delete
b1 = fp1.read(bufsize)
[67] Fix | Delete
b2 = fp2.read(bufsize)
[68] Fix | Delete
if b1 != b2:
[69] Fix | Delete
return False
[70] Fix | Delete
if not b1:
[71] Fix | Delete
return True
[72] Fix | Delete
[73] Fix | Delete
# Directory comparison class.
[74] Fix | Delete
#
[75] Fix | Delete
class dircmp:
[76] Fix | Delete
"""A class that manages the comparison of 2 directories.
[77] Fix | Delete
[78] Fix | Delete
dircmp(a,b,ignore=None,hide=None)
[79] Fix | Delete
A and B are directories.
[80] Fix | Delete
IGNORE is a list of names to ignore,
[81] Fix | Delete
defaults to ['RCS', 'CVS', 'tags'].
[82] Fix | Delete
HIDE is a list of names to hide,
[83] Fix | Delete
defaults to [os.curdir, os.pardir].
[84] Fix | Delete
[85] Fix | Delete
High level usage:
[86] Fix | Delete
x = dircmp(dir1, dir2)
[87] Fix | Delete
x.report() -> prints a report on the differences between dir1 and dir2
[88] Fix | Delete
or
[89] Fix | Delete
x.report_partial_closure() -> prints report on differences between dir1
[90] Fix | Delete
and dir2, and reports on common immediate subdirectories.
[91] Fix | Delete
x.report_full_closure() -> like report_partial_closure,
[92] Fix | Delete
but fully recursive.
[93] Fix | Delete
[94] Fix | Delete
Attributes:
[95] Fix | Delete
left_list, right_list: The files in dir1 and dir2,
[96] Fix | Delete
filtered by hide and ignore.
[97] Fix | Delete
common: a list of names in both dir1 and dir2.
[98] Fix | Delete
left_only, right_only: names only in dir1, dir2.
[99] Fix | Delete
common_dirs: subdirectories in both dir1 and dir2.
[100] Fix | Delete
common_files: files in both dir1 and dir2.
[101] Fix | Delete
common_funny: names in both dir1 and dir2 where the type differs between
[102] Fix | Delete
dir1 and dir2, or the name is not stat-able.
[103] Fix | Delete
same_files: list of identical files.
[104] Fix | Delete
diff_files: list of filenames which differ.
[105] Fix | Delete
funny_files: list of files which could not be compared.
[106] Fix | Delete
subdirs: a dictionary of dircmp objects, keyed by names in common_dirs.
[107] Fix | Delete
"""
[108] Fix | Delete
[109] Fix | Delete
def __init__(self, a, b, ignore=None, hide=None): # Initialize
[110] Fix | Delete
self.left = a
[111] Fix | Delete
self.right = b
[112] Fix | Delete
if hide is None:
[113] Fix | Delete
self.hide = [os.curdir, os.pardir] # Names never to be shown
[114] Fix | Delete
else:
[115] Fix | Delete
self.hide = hide
[116] Fix | Delete
if ignore is None:
[117] Fix | Delete
self.ignore = ['RCS', 'CVS', 'tags'] # Names ignored in comparison
[118] Fix | Delete
else:
[119] Fix | Delete
self.ignore = ignore
[120] Fix | Delete
[121] Fix | Delete
def phase0(self): # Compare everything except common subdirectories
[122] Fix | Delete
self.left_list = _filter(os.listdir(self.left),
[123] Fix | Delete
self.hide+self.ignore)
[124] Fix | Delete
self.right_list = _filter(os.listdir(self.right),
[125] Fix | Delete
self.hide+self.ignore)
[126] Fix | Delete
self.left_list.sort()
[127] Fix | Delete
self.right_list.sort()
[128] Fix | Delete
[129] Fix | Delete
def phase1(self): # Compute common names
[130] Fix | Delete
a = dict(izip(imap(os.path.normcase, self.left_list), self.left_list))
[131] Fix | Delete
b = dict(izip(imap(os.path.normcase, self.right_list), self.right_list))
[132] Fix | Delete
self.common = map(a.__getitem__, ifilter(b.__contains__, a))
[133] Fix | Delete
self.left_only = map(a.__getitem__, ifilterfalse(b.__contains__, a))
[134] Fix | Delete
self.right_only = map(b.__getitem__, ifilterfalse(a.__contains__, b))
[135] Fix | Delete
[136] Fix | Delete
def phase2(self): # Distinguish files, directories, funnies
[137] Fix | Delete
self.common_dirs = []
[138] Fix | Delete
self.common_files = []
[139] Fix | Delete
self.common_funny = []
[140] Fix | Delete
[141] Fix | Delete
for x in self.common:
[142] Fix | Delete
a_path = os.path.join(self.left, x)
[143] Fix | Delete
b_path = os.path.join(self.right, x)
[144] Fix | Delete
[145] Fix | Delete
ok = 1
[146] Fix | Delete
try:
[147] Fix | Delete
a_stat = os.stat(a_path)
[148] Fix | Delete
except os.error, why:
[149] Fix | Delete
# print 'Can\'t stat', a_path, ':', why[1]
[150] Fix | Delete
ok = 0
[151] Fix | Delete
try:
[152] Fix | Delete
b_stat = os.stat(b_path)
[153] Fix | Delete
except os.error, why:
[154] Fix | Delete
# print 'Can\'t stat', b_path, ':', why[1]
[155] Fix | Delete
ok = 0
[156] Fix | Delete
[157] Fix | Delete
if ok:
[158] Fix | Delete
a_type = stat.S_IFMT(a_stat.st_mode)
[159] Fix | Delete
b_type = stat.S_IFMT(b_stat.st_mode)
[160] Fix | Delete
if a_type != b_type:
[161] Fix | Delete
self.common_funny.append(x)
[162] Fix | Delete
elif stat.S_ISDIR(a_type):
[163] Fix | Delete
self.common_dirs.append(x)
[164] Fix | Delete
elif stat.S_ISREG(a_type):
[165] Fix | Delete
self.common_files.append(x)
[166] Fix | Delete
else:
[167] Fix | Delete
self.common_funny.append(x)
[168] Fix | Delete
else:
[169] Fix | Delete
self.common_funny.append(x)
[170] Fix | Delete
[171] Fix | Delete
def phase3(self): # Find out differences between common files
[172] Fix | Delete
xx = cmpfiles(self.left, self.right, self.common_files)
[173] Fix | Delete
self.same_files, self.diff_files, self.funny_files = xx
[174] Fix | Delete
[175] Fix | Delete
def phase4(self): # Find out differences between common subdirectories
[176] Fix | Delete
# A new dircmp object is created for each common subdirectory,
[177] Fix | Delete
# these are stored in a dictionary indexed by filename.
[178] Fix | Delete
# The hide and ignore properties are inherited from the parent
[179] Fix | Delete
self.subdirs = {}
[180] Fix | Delete
for x in self.common_dirs:
[181] Fix | Delete
a_x = os.path.join(self.left, x)
[182] Fix | Delete
b_x = os.path.join(self.right, x)
[183] Fix | Delete
self.subdirs[x] = dircmp(a_x, b_x, self.ignore, self.hide)
[184] Fix | Delete
[185] Fix | Delete
def phase4_closure(self): # Recursively call phase4() on subdirectories
[186] Fix | Delete
self.phase4()
[187] Fix | Delete
for sd in self.subdirs.itervalues():
[188] Fix | Delete
sd.phase4_closure()
[189] Fix | Delete
[190] Fix | Delete
def report(self): # Print a report on the differences between a and b
[191] Fix | Delete
# Output format is purposely lousy
[192] Fix | Delete
print 'diff', self.left, self.right
[193] Fix | Delete
if self.left_only:
[194] Fix | Delete
self.left_only.sort()
[195] Fix | Delete
print 'Only in', self.left, ':', self.left_only
[196] Fix | Delete
if self.right_only:
[197] Fix | Delete
self.right_only.sort()
[198] Fix | Delete
print 'Only in', self.right, ':', self.right_only
[199] Fix | Delete
if self.same_files:
[200] Fix | Delete
self.same_files.sort()
[201] Fix | Delete
print 'Identical files :', self.same_files
[202] Fix | Delete
if self.diff_files:
[203] Fix | Delete
self.diff_files.sort()
[204] Fix | Delete
print 'Differing files :', self.diff_files
[205] Fix | Delete
if self.funny_files:
[206] Fix | Delete
self.funny_files.sort()
[207] Fix | Delete
print 'Trouble with common files :', self.funny_files
[208] Fix | Delete
if self.common_dirs:
[209] Fix | Delete
self.common_dirs.sort()
[210] Fix | Delete
print 'Common subdirectories :', self.common_dirs
[211] Fix | Delete
if self.common_funny:
[212] Fix | Delete
self.common_funny.sort()
[213] Fix | Delete
print 'Common funny cases :', self.common_funny
[214] Fix | Delete
[215] Fix | Delete
def report_partial_closure(self): # Print reports on self and on subdirs
[216] Fix | Delete
self.report()
[217] Fix | Delete
for sd in self.subdirs.itervalues():
[218] Fix | Delete
print
[219] Fix | Delete
sd.report()
[220] Fix | Delete
[221] Fix | Delete
def report_full_closure(self): # Report on self and subdirs recursively
[222] Fix | Delete
self.report()
[223] Fix | Delete
for sd in self.subdirs.itervalues():
[224] Fix | Delete
print
[225] Fix | Delete
sd.report_full_closure()
[226] Fix | Delete
[227] Fix | Delete
methodmap = dict(subdirs=phase4,
[228] Fix | Delete
same_files=phase3, diff_files=phase3, funny_files=phase3,
[229] Fix | Delete
common_dirs = phase2, common_files=phase2, common_funny=phase2,
[230] Fix | Delete
common=phase1, left_only=phase1, right_only=phase1,
[231] Fix | Delete
left_list=phase0, right_list=phase0)
[232] Fix | Delete
[233] Fix | Delete
def __getattr__(self, attr):
[234] Fix | Delete
if attr not in self.methodmap:
[235] Fix | Delete
raise AttributeError, attr
[236] Fix | Delete
self.methodmap[attr](self)
[237] Fix | Delete
return getattr(self, attr)
[238] Fix | Delete
[239] Fix | Delete
def cmpfiles(a, b, common, shallow=1):
[240] Fix | Delete
"""Compare common files in two directories.
[241] Fix | Delete
[242] Fix | Delete
a, b -- directory names
[243] Fix | Delete
common -- list of file names found in both directories
[244] Fix | Delete
shallow -- if true, do comparison based solely on stat() information
[245] Fix | Delete
[246] Fix | Delete
Returns a tuple of three lists:
[247] Fix | Delete
files that compare equal
[248] Fix | Delete
files that are different
[249] Fix | Delete
filenames that aren't regular files.
[250] Fix | Delete
[251] Fix | Delete
"""
[252] Fix | Delete
res = ([], [], [])
[253] Fix | Delete
for x in common:
[254] Fix | Delete
ax = os.path.join(a, x)
[255] Fix | Delete
bx = os.path.join(b, x)
[256] Fix | Delete
res[_cmp(ax, bx, shallow)].append(x)
[257] Fix | Delete
return res
[258] Fix | Delete
[259] Fix | Delete
[260] Fix | Delete
# Compare two files.
[261] Fix | Delete
# Return:
[262] Fix | Delete
# 0 for equal
[263] Fix | Delete
# 1 for different
[264] Fix | Delete
# 2 for funny cases (can't stat, etc.)
[265] Fix | Delete
#
[266] Fix | Delete
def _cmp(a, b, sh, abs=abs, cmp=cmp):
[267] Fix | Delete
try:
[268] Fix | Delete
return not abs(cmp(a, b, sh))
[269] Fix | Delete
except (os.error, IOError):
[270] Fix | Delete
return 2
[271] Fix | Delete
[272] Fix | Delete
[273] Fix | Delete
# Return a copy with items that occur in skip removed.
[274] Fix | Delete
#
[275] Fix | Delete
def _filter(flist, skip):
[276] Fix | Delete
return list(ifilterfalse(skip.__contains__, flist))
[277] Fix | Delete
[278] Fix | Delete
[279] Fix | Delete
# Demonstration and testing.
[280] Fix | Delete
#
[281] Fix | Delete
def demo():
[282] Fix | Delete
import sys
[283] Fix | Delete
import getopt
[284] Fix | Delete
options, args = getopt.getopt(sys.argv[1:], 'r')
[285] Fix | Delete
if len(args) != 2:
[286] Fix | Delete
raise getopt.GetoptError('need exactly two args', None)
[287] Fix | Delete
dd = dircmp(args[0], args[1])
[288] Fix | Delete
if ('-r', '') in options:
[289] Fix | Delete
dd.report_full_closure()
[290] Fix | Delete
else:
[291] Fix | Delete
dd.report()
[292] Fix | Delete
[293] Fix | Delete
if __name__ == '__main__':
[294] Fix | Delete
demo()
[295] Fix | Delete
[296] Fix | Delete
It is recommended that you Edit text format, this type of Fix handles quite a lot in one request
Function