虽然现在有很多图形界面的diff工具,但对于有命令行情节的人来说,当飞快的在terminal下敲击键盘时,总不希望再拿鼠标去点击其它地方,况且有时候图形界面占用资源多,我的MBA就经常启动diffmerge时卡住,但vimdiff又只能在一个标签里比较一组文件的diff,如果想比较两个目录下文件的diff,它就显得无能为力了

假设我们要实现一个工具叫diffdir,先让我们脑洞打开设想一下它应该是怎样的

  1. 我希望能列出两个目录下文件名相同但内容不同的所有文件,并进行编号
  2. 我希望通过选择编号,打开需要比较diff的文件
  3. 如果想比较多组文件的diff,我希望每个vim标签打开一组文件比较
  4. 最好能过滤掉非文本文件,因为我不希望用vim打开一对二进制乱码
  5. 最好还能有交互,我可以选择只查看我感兴趣的文件,而不是一次打开所有文件的diff,当退出vim时我还可以继续选择

假设有两个目录分别是A和B,目录结构如下

A
├── file1
├── file2
└── file3

B和A目录结构以及对应文件名都相同,其中file1和file2的内容不同,file3内容相同,那么当我们运行diffdir A B时,它应该是这样的界面

当我们选择编号1时,vim会打开一个标签对比两个目录下file1的差异
当我们选择1,21-2时,vim会打开两个标签分别比较file1和file2的差异
由于这个例子有diff的文件数量较少,我们还可以选择a一次打开所有文件的diff
如果diff文件个数较多,我们可以分批打开,并且当我们退出vim后还可以继续选择

接下来是实现

vim比较文件diff

我们都知道vimdiff的用法,其实vimdiff A/file1 B/file1等价于vim -d A/file1 B/file2,又或者更原始一点,我们可以分两步来比较两个文件的diff

  1. 执行vim A/file1
  2. 在normal模式下输入:vertical diffsplit B/file1

虽然人们不会用这么麻烦的命令去比价文件的diff,但往往最基本的命令反而能组合出更多的功能,就像搭积木一样,我们只需要几个基本的形状,就可以通过自己的想象搭建多彩的世界,而vim的这些基本命令就像积木一样,我们要做的是利于好这些积木

vim在新标签比较文件diff

假设我们已经用上面的命令打开了vim并比较file1的diff,如果我们希望新建一个标签来比较file2的diff呢,还是要用到基本的ex命令

  1. 在normal模式下执行:tabnew A/file2
  2. 在normal模式下执行:vertical diffsplit B/file1

vim批量执行命令

以上两个示例就是我们需要的积木,有了积木,我们就可以组合出强大的命令,现在要做的是同时打开两组文件的diff,并且每个标签一组diff

通过查看vim帮助我们发现vim有如下两个参数

-c <command>         加载第一个文件后执行 <command>
-S <session>         加载第一个文件后执行文件 <session>

这两个参数都可以让vim启动时执行一些命令,其中-c是从参数读取命令,-S是从文件读取命令,于是我们就可以将需要执行的命令存入文件,启动vim时通过-S参数加载该文件,就能达到我们批量执行命令的目的。假设我们需要打开两个标签,分别比较A,B目录下file1和file2的diff,事先创建vim.script如下(文件名随意,最好采用绝对路径,以免受到vim配置里autochdir的影响)

edit A/file1
vertical diffsplit B/file1
tabnew A/file2
vertical diffsplit B/file2

然后执行vim -S vim.script,看看是否如你所愿,打开了两个标签,分别比较file1和file2的diff。注意,为了

最终实现

既然有了这些积木,那我们就可以灵活的根据需要编写脚本实现我们的需求,下面是我最终的实现,也可以在github上查看源码
https://github.com/handy1989/vim/blob/master/diffdir

#!/bin/bash
if [ $# -ne 2 ];thenecho "Usage:$0 dir1 dir2"exit 1
fi
if [ ! -d $1 -o ! -d $2 ];thenecho "$1 or $2 is not derectory!"exit 1
fi## 注意,Mac的readlink程序和GNU readlink功能不同,Mac需要下载greadlink
arg1=`greadlink -f $1`
arg2=`greadlink -f $2`tmp_dir=/tmp/tmp.$$
rm -rf $tmp_dir
mkdir -p $tmp_dir || exit 0
#echo $tmp_dirtrap "rm -rf $tmp_dir; exit 0" SIGINT SIGTERM## 注意,Mac和Linux的MD5程序不同,请根据需求使用,这里是Mac版的用法
function get_file_md5
{if [ $# -ne 1  ];thenecho "get_file_md5 arg num error!"return 1filocal file=$1md5 $file | awk -F"=" '{print $2}'
}function myexit
{rm -rf $tmp_direxit 0
}function show_diff
{if [ $# -ne 1 ];thenreturn 1filocal diff_file=$1echo "diff file:"printf "    %-55s  %-52s\n" $arg1 $arg2if [ -f $tmp_dir/A_ony_file ];thenawk '{printf("    [%2d] %-50s\n", NR, $1)}' $tmp_dir/A_ony_filepython -c 'print "-"*100'fiawk '{printf("    [%2d] %-50s  %-50s\n", NR, $1, $1)}' $diff_fileecho "(s):show diff files (a):open all diff files (q):exit"echo
}function check_value
{local diff_file=$1local value=$2tmp_file=$tmp_dir/tmp_file>$tmp_filefor numbers in `echo "$value" | tr ',' ' '`donf=`echo "$numbers" | awk -F"-" '{print NF}'`if [ $nf -ne 1 -a $nf -ne 2 ];thenreturn 1fibegin=`echo "$numbers" | awk -F"-" '{print $1}'`end=`echo "$numbers" | awk -F"-" '{print $2}'`if [ -z "$end" ];thensed -n $begin'p' $diff_file >> $tmp_fileelseif [ "$end" -lt $begin ];thenreturn 1fised -n $begin','$end'p' $diff_file >> $tmp_filefiif [ $? -ne 0 ];thenreturn 1fidoneawk -v dir1=$arg1 -v dir2=$arg2 '{if (NR==1){printf("edit %s/%s\nvertical diffsplit %s/%s\n", dir1, $0, dir2, $0)}else{printf("tabnew %s/%s\nvertical diffsplit %s/%s\n", dir1, $0, dir2, $0)}}' $tmp_file
}#############################################################
# 获取diff info
#############################################################
for file in `find $arg1 | grep -v "/\." | grep -v "^\."`
dofile_relative_name=${file#$arg1/}file $file | grep -Eq "text"if [ $? -ne 0 ];thencontinuefiif [ -f $arg2/$file_relative_name ];thenfile $arg2/$file_relative_name | grep -Eq "text"if [ $? -ne 0 ];thencontinuefimd5_1=`get_file_md5 $file`md5_2=`get_file_md5 $arg2/$file_relative_name`if [[ "$md5_1" = "$md5_2" ]];thencontinuefi## file not sameecho "$file_relative_name" >> $tmp_dir/diff_fileelseecho "$file_relative_name" >> $tmp_dir/A_ony_filefi
done#############################################################
# 根据输入标签打开用vim打开文件比较diff
#############################################################
if [ ! -f $tmp_dir/diff_file ];thenexit
fishow_diff $tmp_dir/diff_file
while true
doecho -n "Please choose file number list (like this:1,3-4,5):"read valueif [[ "$value" = "s" ]] || [[ "$value" = "S" ]];thenshow_diff $tmp_dir/diff_filecontinueelif [[ "$value" = "q" ]] || [[ "$value" = "Q" ]];thenmyexitelif [[ "$value" = "a" ]] || [ "$value" = "A" ];thenvalue="1-$"fivim_script=`check_value $tmp_dir/diff_file "$value" 2>/dev/null`if [ $? -ne 0 ];thenecho "invalid parameter[$value]!"elsevim -c "$vim_script"fi
done

vim比较目录diff相关推荐

  1. vim 树形目录插件NERDTree安装及简单用法

    来源:http://blog.csdn.net/love__coder/article/details/6659103 1.安装NERDTree插件 先下载,官网:http://www.vim.org ...

  2. Linux 中去除 vi/vim 和 git diff 中的 ^M 问题解决办法

    去除 vi/vim 和 git diff 中的 ^M 问题解决办法 问题现象 初步分析 进一步查看 问题解决 Source Insight dos2unix Nodpad++ Vim sed 命令 综 ...

  3. 在linux中建立一个vim的目录,Linux学习笔记一(目录结构、Vim编辑器、用户管理)...

    1.Linux介绍 linux是一个开源.免费的操做系统,其稳定性.安全性.处理多并发已经获得 业界的承认,目前不少企业级的项目都会部署到Linux/unix系统上. Linux主要的发行版: Ubu ...

  4. vim树形目录NERDTree

    https://m.linuxidc.com/Linux/2013-06/86048.htm

  5. linux(debian)下的vim diff时 报错E97解决,文件夹对比meld,beyond compare

    1:在用vim比对两个文件时,发现报错了.我用的debian stable,vim是aptitude 过来的vim7.2 2:于是跟踪下diff [html] view plaincopy root@ ...

  6. VIM入门必读(转)

    --整理自互联网 Vi IMproved (VIM) 是 Bram Moolenaar 开发的与 UNIX 下的通用文本编辑器 vi 兼容并且更加强大的文本编辑器.它支持语法变色.正规表达式匹配与替换 ...

  7. Vim配置IDE开发环境

    我的vim IDE界面: 1.安装Vim和Vim基本插件 首先安装好Vim和Vim的基本插件.这些使用apt-get安装即可: lingd@ubuntu:~/arm$sudo apt-get inst ...

  8. Linux 中 VIM 的使用

    Vim 官网:http://www.vim.org/ VIM 实用技巧:https://wenku.baidu.com/view/21c5f387d4d8d15abe234ecb.html vim 的 ...

  9. java vim ide_把VIM配置成IDE开发环境 | 学步园

    VIM常用命令 VIM命令图 VIM键盘布局图 VIM键盘布局英文 VIM键盘布局中文 将VIM配置成IDE(通过 VIM基本插件 和VIM配置文件) Ubuntu14下我的VIM IDE配置的效果图 ...

最新文章

  1. PostCSS理解与运用
  2. 资产配置决策系统的MATLAB实现
  3. Demo能为游戏带来什么?
  4. VS2019C++代码出现cout不明确
  5. 简单编程代码表白_用简单代码实现抖音表白神器
  6. pyltp环境的搭建
  7. 2017mysql下载_mysql for visual studio
  8. java班级管理系统代码_基于jsp的班级管理系统-JavaEE实现班级管理系统 - java项目源码...
  9. 解决了Microsoft Visual C++ Build Tools下载/解决Visual C++ 14.0 is required的问题
  10. 基于GPU加速的车牌识别算法体验
  11. python圣斗士修炼(十八):访问mysql数据库
  12. Webpack 实战入门系列(三):生产配置、样式文件分离及输出清理
  13. 函数型数据主成分分析(FPCA)
  14. 数字滚动(微信小程序)
  15. Gmail、Orkut和Wallop的不限量,不限时邀请
  16. 读书笔记《人人都是产品经理》
  17. mysql运行sql文件不成功,圆我大厂梦!
  18. rstudio协整检验代码
  19. Skylin CityBuilder 6.6.1 提示授权过期解决(License Manager中显示未过期)
  20. hadoop配置、运行错误总结

热门文章

  1. TTL转RS485电路(自动收发)---分享原理图及参考资料
  2. 双目相机实现物体三维重建,得到三维点云
  3. Oracle索引的理解
  4. Maven项目 springsecurity配置
  5. php volist中作判断,ThinkPHP模板中判断volist循环的最后一条记录的验证方法
  6. LeetCode 每日一题1006. 笨阶乘
  7. 正定矩阵的相关性质,凸锥
  8. Mysql统计分组后每组数据与每组数量区别
  9. 提交按钮在form之外的提交方式,提交按钮提交页面任意表单
  10. 一正云系统服务器搭建,腾正云服务器