51

I know that Vim's diff mode (vimdiff) allows us to compare the contents of two (or more) files.

But it is possible to compare content of multiple files across directories in order to merge two directories recursively (like DiffMerge and similar tools)?

2
  • Is a VCS of any kind in use for your respective folders? That would open up a whole range of answers and plugins that may not be available for flat folders.
    – Caleb
    Feb 14, 2015 at 9:25
  • see github.com/balki/vimtabdiff
    – balki
    Dec 14, 2022 at 18:28

5 Answers 5

42

There is DirDiff.vim plugin to diff and merge two directories recursively.

It performs a recursive diff on two directories and generate a diff "window". Based on that window you can perform various diff operations such as opening two files in Vim's diff mode, copy the file or directory recursively to the other, or remove the directory tree from the source directory.

Usage:

:DirDiff <dir1> <dir2>

For more information / help: :help dirdiff

Thus from the command line: vim -c 'DirDiff foo bar'

See the screenshot:

wlee screenshot

See also:

two random directories

0
7

If you just want to just use vimdiff without installing anything extra, the following command will open all the differing files in succession letting you look at the changes with vimdiff:

    for files in $(diff -rq dir1 dir2|grep 'differ$'|sed "s/^Files //g;s/ differ$//g;s/ and /:/g"); do 
        vimdiff ${files%:*} ${files#*:}; 
    done
1
  • If you have a filename with a timestamp, which components are separated by colons, then this will not work. In that case, you have to replace the three colons in the snippet by another, unique character, like a vertical bar or so
    – nst0022
    Jul 6 at 15:11
4

I've wanted the same for a while. The best solution I found was to use vdwrap, which works amazingly well. All it does is wrap git difftool --dir-diff for vimdiff. It doesn't require any vim plugins.

All you need to do is tell git difftool to use vdwrap:

git config --global difftool.vdwrap.cmd '/full/path/vdwrap $LOCAL $REMOTE'
git config --global diff.tool vdwrap

The next time you use git difftool, it will open Vim with separate Vim tabs for each pairs of files.

A caveat is that it's a Zsh script. It should be pretty simple to convert it to a bash script but I haven't given that a go.

1
4

I use a wrapper script in python to merge files (see below). This is a simplified version of what I use to merge my ~/.vim dirs and such.

It should work in Python 2 and 3; but probably not in very old versions of Python as shipped with CentOS and some other distros.

Be aware that some checks (like the one for binary files, or if the files are the same) are not very fast (it reads the entire file); you could remove them if you want.

It also doesn't report if a is only present in one of the directories...

#!/usr/bin/env python
from __future__ import print_function
import hashlib, os, subprocess, sys

if len(sys.argv) < 3:
    print('Usage: {} dir1 dir2'.format(sys.argv[0]))
    sys.exit(1)

dir1 = os.path.realpath(sys.argv[1])
dir2 = os.path.realpath(sys.argv[2])

for root, dirs, files in os.walk(dir1):
    for f in files:
        f1 = '{}/{}'.format(root, f)
        f2 = f1.replace(dir1, dir2, 1)

        # Don't diff files over 1MiB
        if os.stat(f1).st_size > 1048576 or os.stat(f2).st_size > 1048576: continue

        # Check if files are the same; in which case a diff is useless
        h1 = hashlib.sha256(open(f1, 'rb').read()).hexdigest()
        h2 = hashlib.sha256(open(f2, 'rb').read()).hexdigest()
        if h1 == h2: continue

        # Don't diff binary files
        if open(f1, 'rb').read().find(b'\000') >= 0: continue

        subprocess.call(['vimdiff', f1, f2])
1

There's a lightweight solution for that:

  1. Set up vimdiffext plugin.
  2. Do diff dir1 dir2 | vim -R - at shell.

It will add folds and side-by-side comparison for changed files.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.