Vim Tips Wiki
Advertisement
Tip 416 Printable Monobook Previous Next

created January 31, 2003 · complexity basic · author Juan M. Medina · version 6.0


I read a couple postings of people having this issue, even if they have a diff program in their path when running on Windows platforms.

Check out your _vimrc file, function "MyDiff". If the path to the diff file contains ANY spaces, enclose the path in double quotes. Alternatively you can remove the path and just leave the diff file and check.

This is the line that if fixed in my _vimrc:

Changed

silent execute '!C:\Program Files\Vim\vim61\diff -a ' . opt . v:fname_in . ' ' . v:fname_new . ' > ' . v:fname_out

To be:

silent execute '!"C:\Program Files\Vim\vim61\diff" -a ' . opt . v:fname_in . ' ' . v:fname_new . ' > ' . v:fname_out

I am running the diff program that comes with CygWin and it works just fine.

Comments

The instructions make a lot more sense when you find this example in the documentation:

set diffexpr=MyDiff()
function MyDiff()
  let opt = ""
  if &diffopt =~ "icase"
    let opt = opt . "-i "
  endif
  if &diffopt =~ "iwhite"
    let opt = opt . "-b "
  endif
  silent execute "!diff -a " . opt . v:fname_in . " " . v:fname_new .
        \ " > " . v:fname_out
endfunction

And don't forget to update your path to the diff program if you upgrade to vim6.2


To correct E97 I found that I had to add double quotes around the entire command, like so:

silent execute '!""C:\Program Files\vim\vim62\diff.exe" -a ' . opt . '"' . v:fname_in . '" "' . v:fname_new . '" > "' . v:fname_out . '""'

I am running gvim 6.2 on a Win2000 Server. My shell command, "cmd.exe /c", was stripping the double quotes around Program Files and causing the execution to fail.


I'm running gvim 6.1 on Windows 2000, not the OS of my choice.

My problem was as simple as diff.exe not being in the PATH.

I added a diff.bat to my a "bin" directory that was in the path and it solved it:

@"C:\Program Files\Vim\vim61\diff.exe" %*

I couldn't find MyDiff in my _vimrc. erhaps I had an old _vimrc.


The solution that I found was to modify the default line in the _vimrc and double up the backslashes:

silent execute '!C:\\Vim\\vim62\\diff -a ' . opt . '"' . v:fname_in . '" "' . v:fname_new . '" > "' . v:fname_out . '"'

Since I knew I didn't have spaces in my path, I knew that wasn't the problem.

But a good way to find out what is causing the problem for you in each different case, the solution is fairly straightforward: remove the "silent" at the beginning of the line. This will let you see the execution of the command and the more detailed error messages returned from the diff call. That's how I figured mine out, since the output said:

C:/mks/mksnt/sh.exe -c "C:\Vim\vim62\diff -a "..." "..." > "...""
C:Vimvim62diff: not found
shell returned 127

That "C:Vimvim62diff" gave it away. You'll probably find useful info in this same output.


Well, the remove silent was the key for me. It let me find the problem anyway.

On Windows XP, the error reported that C:\Program is not recognized as an internal or external command, operable program or batch file.

I'm using Microsoft Windows XP [Version 5.1.2600].

I removed the reference to path as I had added the c:\program files\vim\vim62 to my path environment variable

_vimrc line in my file = silent execute '!diff -a ' . opt . v:fname_in . ' ' . v:fname_new . ' > ' . v:fname_out


Adding the path to cygwin's diff worked for me.


I changed the path to use forward slashes and changed Program Files to Progra~1, stripped out the extra double quotes, and it started working.


I just copied diff.exe into my C:/winnnt/system32 folder and changed the line to just be diff -a. Worked like a charm.


There's no general solution to fix this problem out-of-the-box. It depends on the idiosincrasies of the command processor (shell) that is used to "silent execute" the line. For instance, on my winxp box I usually start gvim from a 4nt.exe command line, which in turn sets COMSPEC to be 4nt.exe instead of the default cmd.exe. So, in my case, the simplest way to fix MyDiff is to change it this way:

silent execute '!C:\Progra~1\vim\vim63\diff -a ' . opt . v:fname_in . ' ' . v:fname_new . ' > ' . v:fname_out

which runs: 4nt.exe /c c:\Progra~1\vim\vim63\diff -a ...

Perhaps MyDiff out-of-the-box could be made more robust if it used the short filename (no blanks) form instead of attempting to quote spaces. I don't know what to do with backward or forward slashes, though. If cygwin bash is used, I think it requires forward slashes, while 4nt needs backward slashes.


I am running Vim 6.3 on Windows 2000. I copied diff.exe from cygwin to c:\WINNT\system32 and that fixed the problem, without changing anything else.

I removed diff.exe from c:\WINNT\system32 and added c:\cygwin\bin to the windows path environment variable, and that also worked.

I installed gvim for windows frimthe vim.org download, and there was not diff.exe included in the distribution. There was no MyDiff function to be found, except in the documentation. There was no 'silent execute' call to be found in any file either - not in _vimrc, or anywhere else in the distribution. The distribution I downloaded and installed was version 6.3, the non-ole version, and the runtime files as well. I installed everything in C:\Program Files, where unzipping everything to that destination put the distribution in C:\Program Files\vim\vim63, and C:\Program Files\vim\vimfiles. Hopefully this will help vim63 users. Just to satisfy my curiousity, did I do something dramatically wronge, that there was not Mydiff() function, no "silent execute" calls, and no idff.exe file?


Just do what is in the Documentation . Read and follow directions how hard is that!


I tried all of the suggestions in this thread but they didn't work for me. I finally determined my problem was due to the fact I could not write temp files to the locaton the shell (cmd.exe) wanted to write them. My (Windows) desktop has policies forced upon it from the network.

The error messages (*e97* and *e485*) and the "verbose" setting helped me to make this determination.

To correct my problem I was able to change the "TMP" / "TEMP" variable to a different location (not my profile's location) and the diff command (as well as other commands such as grep) began to work.

So if the suggestions in this thread aren't working for you, try to change your "TMP" / "TEMP" variables.


I spent a lot of time to get this to work, mostly because I work in an unsual environment: Windows 2000, bash.exe (from http://www.steve.org.uk/Software/bash/) with the UnixUtils (from http://unxutils.sourceforge.net/). The main advantage is that I can work very Unix-like, without a complete cygwin installation.

However, I hat to "set shell=bash.exe" in my _vimrc file to get it working. Note that bash.exe must be in the PATH, of course.


I found where diff.exe was located. On my system, it is at: C:\Program Files\vim\vim61 I just added that to the Path in the system environment variables. Works fine now.

The suggestions that moved a copy of the diff.exe to other locations are doing the same thing. Just moving diff.exe to a place the operating system can find it.


After trying most of the solutions above, I can now create diffs. Adding the location of the diff command to my path did not work. I could create diffs from a Windows cmd shell, and I could create them from gvim if I started gvim from a cmd shell, but I could not create them if I started gvim from the RMB (right mouse button context menu). The solution was found by removing the "silent" entry from the _vimrc as suggested above, and then working thru the error messages. My final entries are:

if &sh =~ '\<cmd'
  silent execute '!""C:\Program Files\Vim\vim63\diff" ' . opt . arg1 . ' ' . arg2 . ' > ' . arg3 . '"'
else
  silent execute '!C:/Progra~1/Vim/vim63/diff ' . opt . arg1 . ' ' . arg2 . ' > ' . arg3
endif

Thanks to all of the others who have contributed.


The hint with the shell fixed my problem. The "execute" used the wrong program, not the cmd.exe.

In _vimrc create the following line:

set shell=cmd.exe

I got the following error when i tried to use diff in gvim 6.3

E10: \ should be followed by /, ? or &
E97: Cannot create diffs

I had changed the following :

oldfile - silent execute '\"!D:\Program Files\vim\vim63\diff\" -a ' . opt . v:fname_in . ' ' . v:fname_new . ' > ' . v:fname_out
newfile - silent execute '!"D:\Program Files\vim\vim63\diff" -a ' . opt . v:fname_in . ' ' . v:fname_new . ' > ' . v:fname_out

And the problem was resolved


I just upgraded from 6.3 to 6.4 and had this problem because the path to gvim.exe and the packaged diff.exe changed. To make it more forwards compatible, I changed the "silent execute" line to this:

silent execute '!"'.$VIMRUNTIME.'\diff" ' . opt . arg1 . ' ' . arg2 . ' > ' . arg3

It works for me, but I don't have any spaces or odd characters in my $VIMRUNTIME directory (C:\vim\vim64\), so give it a test. My goal is to have one line that will work no matter what your vim install directory is named, without having to alter your PATH variable, so long as there is a diff installed in the same directory as vim and gvim. I also never had any problem with backslashes, nor do I have them now, but the double quotes before and after $VIMRUNTIME should at least take care of issues with spaces.


I suggest using forward slashes. You might want to change the following line in your default _vimrc:

Change: C:/Vim/vim63 to where vim lives on your system : (if you dont know where, do this in VIM :echo $VIMRUNTIME )

[old]

"silent execute '!"C:\Vim\vim63\diff.exe" ' . opt . arg1 . ' ' . arg2 . ' > ' . arg3

[new]

silent execute '!"C:/Vim/vim63/diff.exe" ' . opt . arg1 . ' ' . arg2 . ' > ' . arg3

Perhaps adding " " as safety, is always good advice. For my example, there are no spaces in dir names, so you don't need the "".


This seems to work (Win XP SP2). All I'm doing is double-double quotes around the

C:\Program Files\Vim\vim64\diff

part.

Hint: Leave out 'silent' until you sort the error out.

set diffexpr=MyDiff()
function MyDiff()
  let opt = ""
  if &diffopt =~ "icase"
    let opt = opt . "-i "
  endif
  if &diffopt =~ "iwhite"
    let opt = opt . "-b "
  endif
  silent execute '!""C:\Program Files\Vim\vim64\diff"" -a ' . opt . v:fname_in . ' ' . v:fname_new . ' > ' . v:fname_out
endfunction
endif

Advertisement