在Vim的官方网站上有一个支持2个文件夹比较的插件DirDiff, 链接: http://www.vim.org/scripts/script.php?script_id=102. 不过仅支持2个文件夹, 我对齐进行研究并改进后让其支持多个文件夹的文件进行比较.
DirDiff插件的基本原理就是先生成要比较的几个文件夹中的所有文件列表文件, 该文件的每一行对应于一个文件以及它所在的文件夹. 启用文件夹比较模式时, 会载入这个列表文件, 当选中一行时会解析出文件路径, 然后以diff模式分别打开这个文件在不同文件夹下对应的文件进行比较.
这里为了方便, 我就使用Python来生成这个特定格式的文件列表, 然后启动vim 并启动文件夹插件比较.
Python脚本如下:
1 #!/usr/bin/env python
2 # coding:UTF-8
3
4 import os,sys,shutil,subprocess
5 from os import path
6 # 将dirlist中的目录列表下的文件放在一个文件词典filesdict中,
7 # 词典的key是dirlist中某个目录下的文件名(不含该目录名),
8 # value是dirlist中存在对应的key的所有目录
9 def getfilesfromdirs(dirlist):
10 filesdict = {}
11 for onedir in dirlist:
12 onedir = path.realpath(onedir) # 规范化目录名
13 #处理目标路径下(含子目录下)的所有文件
14 for root,dirs,files in os.walk(onedir):
15 # 记录每个文件名所属的目录,同名文件则会属于多个不同目录.
16 # 这样就生成了文件名到文件所在目录的倒排索引
17 for onefile in files:
18 # 若该文件名的键值还未创建则先创建
19 onefile = os.path.join(root,onefile)[len(onedir):]
20 if onefile not in filesdict:
21 filesdict[onefile] = []
22 filesdict[onefile] += [onedir]
23 return filesdict
24
25 def vimDirDiffN(diffdirs):
26 diffbuffer = './vimdirdiffntmpbuffer'
27 filesdict = getfilesfromdirs(diffdirs)
28 fileslines = []
29 for key,values in filesdict.iteritems():
30 fileslines += [' File: '+key+' @ ' + ','.join(values)]
31 write2fileline = str(len(diffdirs))
32 fileslines = '\n'.join(fileslines)
33 dirsymbol = 'A'
34 for onedir in diffdirs:
35 dirline = '<' + dirsymbol + '>' + '=' + onedir
36 write2fileline += '\n' + dirline
37 fileslines = fileslines.replace(onedir,'<' + dirsymbol + '>')
38 dirsymbol = chr(ord(dirsymbol) + 1)
39 write2fileline += '\n\n' + fileslines
40 fp = open(diffbuffer,'w')
41 fp.write(write2fileline)
42 fp.close()
43 subprocess.Popen('gvim -c ":DirDiffN ' + path.join(os.getcwd(),diffbuffer) + '"',shell=True)
44
45 if __name__ == "__main__":
46 if len(sys.argv) > 2:
47 diffdirs = sys.argv[1:]
48 for index in range(0,len(diffdirs)):
49 diffdirs[index] = path.realpath(diffdirs[index])
50 vimDirDiffN(diffdirs)
51 else:
52 print "Interactive Mode."
53 diffdirs = raw_input('input the dirs you want to diff(in List["A","B"]): ')
54 if diffdirs == '':
55 diffdirs = ['f:/PYOutput/old','f:/PYOutput/new','f:/PYOutput/third_merge']
56 else:
57 diffdirs = eval(diffdirs)
58 for index in range(0,len(diffdirs)):
59 diffdirs[index] = path.realpath(diffdirs[index])
60 vimDirDiffN(diffdirs)
61 raw_input('press to exit.')
这个脚本就是读入用户输入需要比较的文件夹列表, 然后扫描文件生成一个比较列表, 启动vim并执行我修改后的多文件夹比较插件DirDiffN.
修改后的DirDiffN插件比较多, 可以从附件下载. DirDiffN插件下载
将DirDiffN放入Vim的插件目录下即可.
效果预览图: