vim比较目录diff

虽然现在有很多图形界面的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 ];then
    echo "Usage:$0 dir1 dir2"
    exit 1
fi
if [ ! -d $1 -o ! -d $2 ];then
    echo "$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_dir

trap "rm -rf $tmp_dir; exit 0" SIGINT SIGTERM

## 注意,Mac和Linux的MD5程序不同,请根据需求使用,这里是Mac版的用法
function get_file_md5
{
    if [ $# -ne 1  ];then
        echo "get_file_md5 arg num error!"
        return 1
    fi
    local file=$1
    md5 $file | awk -F"=" ‘{print $2}‘
}

function myexit
{
    rm -rf $tmp_dir
    exit 0
}

function show_diff
{
    if [ $# -ne 1 ];then
        return 1
    fi
    local diff_file=$1
    echo "diff file:"
    printf "    %-55s  %-52s\n" $arg1 $arg2
    if [ -f $tmp_dir/A_ony_file ];then
        awk ‘{printf("    [%2d] %-50s\n", NR, $1)}‘ $tmp_dir/A_ony_file
        python -c ‘print "-"*100‘
    fi
    awk ‘{printf("    [%2d] %-50s  %-50s\n", NR, $1, $1)}‘ $diff_file
    echo "(s):show diff files (a):open all diff files (q):exit"
    echo
}

function check_value
{
    local diff_file=$1
    local value=$2
    tmp_file=$tmp_dir/tmp_file
    >$tmp_file
    for numbers in `echo "$value" | tr ‘,‘ ‘ ‘`
    do
        nf=`echo "$numbers" | awk -F"-" ‘{print NF}‘`
        if [ $nf -ne 1 -a $nf -ne 2 ];then
            return 1
        fi
        begin=`echo "$numbers" | awk -F"-" ‘{print $1}‘`
        end=`echo "$numbers" | awk -F"-" ‘{print $2}‘`
        if [ -z "$end" ];then
            sed -n $begin‘p‘ $diff_file >> $tmp_file
        else
        if [ "$end" -lt $begin ];then
            return 1
        fi
        sed -n $begin‘,‘$end‘p‘ $diff_file >> $tmp_file
        fi
        if [ $? -ne 0 ];then
        return 1
        fi
    done
    awk -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 "^\."`
do
    file_relative_name=${file#$arg1/}
    file $file | grep -Eq "text"
    if [ $? -ne 0 ];then
        continue
    fi
    if [ -f $arg2/$file_relative_name ];then
        file $arg2/$file_relative_name | grep -Eq "text"
        if [ $? -ne 0 ];then
            continue
        fi
        md5_1=`get_file_md5 $file`
        md5_2=`get_file_md5 $arg2/$file_relative_name`
        if [[ "$md5_1" = "$md5_2" ]];then
            continue
        fi
        ## file not same
        echo "$file_relative_name" >> $tmp_dir/diff_file
    else
        echo "$file_relative_name" >> $tmp_dir/A_ony_file
    fi
done

#############################################################
# 根据输入标签打开用vim打开文件比较diff
#############################################################
if [ ! -f $tmp_dir/diff_file ];then
    exit
fi

show_diff $tmp_dir/diff_file
while true
do
    echo -n "Please choose file number list (like this:1,3-4,5):"
    read value
    if [[ "$value" = "s" ]] || [[ "$value" = "S" ]];then
        show_diff $tmp_dir/diff_file
        continue
    elif [[ "$value" = "q" ]] || [[ "$value" = "Q" ]];then
        myexit
    elif [[ "$value" = "a" ]] || [ "$value" = "A" ];then
        value="1-$"
    fi
    vim_script=`check_value $tmp_dir/diff_file "$value" 2>/dev/null`
    if [ $? -ne 0 ];then
        echo "invalid parameter[$value]!"
    else
        vim -c "$vim_script"
    fi
done
时间: 2024-11-13 06:54:21

vim比较目录diff的相关文章

vim 树形目录插件NERDTree

1,安装NERDTree插件 先下载,官网:http://www.vim.org/scripts/script.php?script_id=1658 解压缩之后,把 plugin/NERD_tree.vim 和doc/NERD_tree.txt分别拷贝到~/.vim/plugin 和 ~/.vim/doc 目录. 2,使用 1.在linux命令行界面,用vim打开一个文件. 2.输入  :NERDTree ,CTRL+D 补全命令, 回车 3.进入当前目录的树形界面,通过小键盘上下键,能移动选中

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

转自: http://blog.csdn.net/love__coder/article/details/6659103 1.安装NERDTree插件 先下载,官网:http://www.vim.org/scripts/script.php?script_id=1658 解压缩之后,把 plugin/NERD_tree.vim 和doc/NERD_tree.txt分别拷贝到~/.vim/plugin 和 ~/.vim/doc 目录. 2.使用 1.在linux命令行界面,输入vim 2.输入  

为vim增加目录浏览插件

NERDTree 是vim的目录浏览插件,使用该插件,可以在vim窗口的一侧浏览目录,使用hjkl浏览目录,用Enter键打开或关闭目录,打开文件.下面来讲述安装方法. 使用该网页进入NERDTree的github主页:https://github.com/scrooloose/nerdtree 该页面提供的命令:cd ~/.vim/bundle && git clone https://github.com/scrooloose/nerdtree.git 然后使用命令:Helptags

vim树形目录

NERD tree树形目录插件 • 插件简介 NERD tree是一款vim树形文件资源管理器插件.NERD tree可以让你在vim中浏览你的文件系统,打开想要的文件或目录. • 插件安装 ? 下载NERD tree,下载地址:http://www.vim.org/scripts/script.php?script_id=1658: ?  存放路径,在Windows系统下路径为:vim安装路径\vimXX\,在Linux系统下安装路径为:/usr/share/vim/vimXX/: ?  将下

vim liunx目录(又忘写了)

vim搜索功能在视图模式输入/+搜索内容 搜索的快捷键n 向下搜索N 向上搜索 vim搜索到的内容是高亮显示的,不取消,退出后还是高亮显示取消高亮显示(两种)a :noh b.搜索一个不可能查到的内容 批量选中删除ctrl+v ->然后光标选中->然后按d ctrl+v 光标移动选中 按d键删除 批量添加ctrl+v ->光标选中->I ->输入添加内容 ->按两次escctrl+v 光标选中 shift+i 进入编辑模式 输入内容 按两次esc vim 的排错隐藏文件

vim目录说明

plugin.autoload.ftplugin有什么区别 很多初用vim的朋友在安装插件时都会有些疑惑.同样的插件,有些教程说安装在plugin目录,有些说安装在ftplugin目录,有些说安装在autoload目录,到底这些目录的区别是什么呢?今天阿驹跟大家解说一下. 一般,我们安装好vim后,应该会创建一个用户vim文件夹,里面的子目录结构和原vim的目录结构几乎一样,例如在windows平台下这个名称是vimfiles,在unix类平台下是~/.vim.但它们的子目录结构都类似下面这样:

VIM中diff的使用

1.启动diff 在VIM中开启diff的方式有很多,下面介绍几种常用的场景. 1.1 外部直接打开两个文件 # 直接使用vimdiff指令vimdiff FILE_1 FILE_2# 使用vim指令加-d参数 vim -d FILE_1 FILE_2 1.2 打开文件之后再进行文件比较 # 先打开一个文件,再打开另一个文件进行对比 vim FILE_1 :vertical diffsplit FILE_2 # 直接打开两个文件,在进行比较 vim -On FILE_1 FILE_2 :diff

[转载] 像 IDE 一样使用 vim

原文: https://github.com/yangyangwithgnu/use_vim_as_ide 看了这篇文章要是再不会用vim就不能怪我了. 所需即所获:像 IDE 一样使用 vim [email protected]2015-02-15 13:30:59 谢谢 捐赠:支付宝 [email protected] .支付宝链接https://shenghuo.alipay.com/send/payment/[email protected] ,支付宝二维码 $_$ 二手书:书,我提高开

Window + Vim + MingW 配置

首先安装Vim , MinGW,假设安装目录为D:\MinGW. 配置环境变量: LIBRARY_PATH=D:\MinGW\lib C_INCLUDE_PATH=D:\MinGW\include CPLUS_INCLUDE_PATH=D:\MinGW\include\c++\3.2.3;d:\MinGW\include\c++\3.2.3\mingw32;D:\MinGW\include\c++\3.2.3\backward;D:\MinGW\include 把D:\MinGW\bin;添加到