Difference between revisions of "Comparing files"

From Vifm Wiki
Jump to: navigation, search
(Plugging the script into vifm)
(Plugging the script into vifm: Fix expansion of file names with quotes)
 
(2 intermediate revisions by 2 users not shown)
Line 1: Line 1:
 
== Comparison script ==
 
== Comparison script ==
  
The script below takes two arguments on the command-line and compares them via <code>[https://en.wikipedia.org/wiki/Diff diff]</code> command. It also echoes generic human-readable answer saying whether two file system objects are equal. As <code>diff</code> compares directories as well as files, paths to directories are valid arguments as well.
+
The script below takes two arguments on the command-line and compares them via <code>[https://en.wikipedia.org/wiki/Diff diff]</code> command. It also echoes generic human-readable answer saying whether two file system objects are equal. As <code>diff</code> is able to compare both directories and files, paths to directories are valid arguments as well.
  
<syntaxhighlight lang="bash">
+
<source lang="bash">
 
#!/bin/bash
 
#!/bin/bash
  
Line 12: Line 12:
  
 
if [ -f "$1" -a -f "$2" ]; then
 
if [ -f "$1" -a -f "$2" ]; then
     : # OK, do nothing here
+
     args=
 
elif [ -d "$1" -a -d "$2" ]; then
 
elif [ -d "$1" -a -d "$2" ]; then
     : # OK, do nothing here
+
     args='-r'
 
else
 
else
 
     if [ -f "$1" ]; then
 
     if [ -f "$1" ]; then
Line 30: Line 30:
 
fi
 
fi
  
if diff "$1" "$2" > /dev/null 2>&1; then
+
if diff $args "$1" "$2" > /dev/null 2>&1; then
 
     echo 'Equal'
 
     echo 'Equal'
 
else
 
else
 
     echo 'Not equal'
 
     echo 'Not equal'
 
fi
 
fi
</syntaxhighlight>
+
</source>
  
 
== Plugging the script into vifm ==
 
== Plugging the script into vifm ==
Line 45: Line 45:
 
# Add following lines to your <code>vifmrc</code>:<code>
 
# Add following lines to your <code>vifmrc</code>:<code>
 
     command! cmpinternal compare-cmd %a %S
 
     command! cmpinternal compare-cmd %a %S
     command! cmp : if expand('%c') == expand('%f')
+
     command! cmp : if expand('%%c') == expand('%%f')
               \ |    echo expand('Comparing %"c and %"C:t ...')
+
               \ |    echo expand('Comparing %%"c and %%"C:t ...')
 
               \ |    cmpinternal %c %C
 
               \ |    cmpinternal %c %C
 
               \ | else
 
               \ | else
               \ |    echo expand('Comparing files: %"f ...')
+
               \ |    echo expand('Comparing files: %%"f ...')
 
               \ |    cmpinternal %f
 
               \ |    cmpinternal %f
 
               \ | endif
 
               \ | endif
Line 56: Line 56:
 
Explanation of key parts:
 
Explanation of key parts:
 
* <code>cmpinternal</code> — a trick to invoke external command. Calling <code>execute "!compare-cmd ... %S"</code> reparses command-line which leads to loosing results of command execution (they are overwritten by execution of <code>if-else-endif</code> block).
 
* <code>cmpinternal</code> — a trick to invoke external command. Calling <code>execute "!compare-cmd ... %S"</code> reparses command-line which leads to loosing results of command execution (they are overwritten by execution of <code>if-else-endif</code> block).
* <code>expand('%c') == expand('%f')</code> — check whether only one file is selected in current pane.
+
* Double percent sign in arguments for the <code>expand()</code> function (e.g. <code>expand('%%c')</code>) — macros are automatically expanded for user-defined commands, so <code>%</code> symbol should be escaped with itself for expansion to be performed by <code>expand()</code> function. It's important as otherwise unescaped quotes or other special characters in file names can break command syntax.
 +
* <code>expand('%%c') == expand('%%f')</code> — check whether only one file is selected in current pane.
  
 
== Usage ==
 
== Usage ==

Latest revision as of 14:25, 15 September 2014

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).