Comparing files

From Vifm Wiki
Jump to: navigation, search

Comparison script[edit]

The script below takes two arguments on the command-line and compares them via diff command. It also echoes generic human-readable answer saying whether two file system objects are equal. As diff is able to compare both directories and files, paths to directories are valid arguments as well.

#!/bin/bash
 
if [ $# != 2 ] ; then
    echo 'Expected exactly two arguments'
    exit 1
fi
 
if [ -f "$1" -a -f "$2" ]; then
    args=
elif [ -d "$1" -a -d "$2" ]; then
    args='-r'
else
    if [ -f "$1" ]; then
        type_of_1='file'
    else
        type_of_1='directory'
    fi
    if [ -f "$2" ]; then
        type_of_2='file'
    else
        type_of_2='directory'
    fi
    echo "Arguments are of different type ($type_of_1/$type_of_2)"
    exit 1
fi
 
if diff $args "$1" "$2" > /dev/null 2>&1; then
    echo 'Equal'
else
    echo 'Not equal'
fi

Plugging the script into vifm[edit]

To use it in Vifm:

  1. Save the script as compare-cmd (not cmp or compare to avoid name conflict with existing tools) at one of directories listed in your $PATH environment variable or under $VIFM/scripts (most likely that it's ~/.vifm/scripts).
  2. On Unix-like operating systems make the script file executable by running
    chmod +x compare-cmp
  3. Add following lines to your vifmrc:
   command! cmpinternal compare-cmd %a %S
   command! cmp : if expand('%%c') == expand('%%f')
              \ |     echo expand('Comparing %%"c and %%"C:t ...')
              \ |     cmpinternal %c %C
              \ | else
              \ |     echo expand('Comparing files: %%"f ...')
              \ |     cmpinternal %f
              \ | endif

Explanation of key parts:

  • cmpinternal — a trick to invoke external command. Calling execute "!compare-cmd ... %S" reparses command-line which leads to loosing results of command execution (they are overwritten by execution of if-else-endif block).
  • Double percent sign in arguments for the expand() function (e.g. expand('%%c')) — macros are automatically expanded for user-defined commands, so % symbol should be escaped with itself for expansion to be performed by expand() function. It's important as otherwise unescaped quotes or other special characters in file names can break command syntax.
  • expand('%%c') == expand('%%f') — check whether only one file is selected in current pane.

Usage[edit]

  • Run :cmp without selection or with single file selection to compare files under cursors in two panes.
  • Run :cmp after selecting two files in the current pane to compare them.

Results are printed on the status bar (because of %S macro in cmdinternal).