Tips Linux Explorers   All Things Linux Forum   Great Linux Links   LinuxClues.com   Hometown    



DIRDIFF SCRIPT
( Diff the content of 2 directories )


In the previous Tip we combined the "find' command with the "diff" command to find the difference in the files located in 2 almost similar directories. It did involve a bit of work but we got the result we were after.

Now imagine if there was a script that could do all the work for you ?
Here is the "dirdiff" script that Ragnar sent me a while back. It compares the contents of two directories ( with the -r option also recursively ) An example of usage is:

CODE
$ dirdiff -r -q  /home/bruno/test-1  /home/bruno/test-2

The results will look similar like this:

QUOTE = Terminal
$ dirdiff -r -q  /home/bruno/test-1  /home/bruno/test-2

FILE: colors.txt
6c6
< # indigo
---
> # indigo-blue
10d10
< # sienna
12a12
> # darkblue
15c15
< # tomato
---
> # tomato-red


It searches the directory, finds the file that is different and shows us where the differences are in that file . . . . . really clever and it saves us the trouble of giving all the commands we had to give in the previous Tip.
Next to the -r and -q options I gave in the example above there are also:

QUOTE
  -b        ignore trailing blanks
  -B        include comparison of binary files
  -c        ignore trailing carriage returns
  -e file  exclude file from comparison
  -E dir    exclude subdirectory from comparison
  -l        list filenames only
  -q        quiet mode (only list filename if there are differences)
  -r        recursive mode (descend all subdirectories)
  -L        show contents of files that only exist in leftdir
  -R        show contents of files that only exist in rightdir
  -T        ignore files that are text in one directory
  -X        ignore files that only exist in one directory



Okay, so here is the script, paste in a text-editor, call it "dirdiff" make it executable with "chmod 755" and move it to /usr/local/bin

SCRIPT

#!/bin/bash
# dirdiff  compares the contents of two directories
# made by Ragnar Paulson 2004

SCRIPT=`basename "$0"`
FILELIST=/tmp/$SCRIPT.list$$
DIFFS=/tmp/$SCRIPT.diffs$$
BADUSAGE="Type \"$SCRIPT -h\" for command usage."

EXCLUDE_LIST=
EXCLUDE_DIRLIST=
BINARY=false
IGNORECR=false
IGNOREEXIST=false
LISTONLY=false
QUIET=false
RECURSIVE=false
SHOWLEFT=false
SHOWRIGHT=false
IGNORETEXT=false
DIFFOPTS=
CMPOPTS=

OPTIND=1
while getopts bBce:E:hlqrLRTX switch; do
   case "$switch" in
   b)
DIFFOPTS="$DIFFOPTS -b"
;;
   B)
BINARY=true
;;
   c)
IGNORECR=true
;;
   e)
EXCLUDE_LIST="$EXCLUDE_LIST $OPTARG"
;;
   E)
       EXCLUDE_DIRLIST="$EXCLUDE_DIRLIST $OPTARG"
    ;;
   h)
echo "$SCRIPT -- Compare files in two directories."
echo "Usage: $SCRIPT [options] leftdir rightdir"
echo "Options:"
echo "   -b        ignore trailing blanks"
echo "   -B        include comparison of binary files"
echo "   -c        ignore trailing carriage returns"
echo "   -e file   exclude file from comparison"
echo "   -E dir    exclude subdirectory from comparison"
echo "   -l        list filenames only"
echo "   -q        quiet mode (only list filename if there are differences)"
echo "   -r        recursive mode (descend all subdirectories)"
echo "   -L        show contents of files that only exist in leftdir"
echo "   -R        show contents of files that only exist in rightdir"
echo "   -T        ignore files that are text in one directory"
echo "   -X        ignore files that only exist in one directory"
exit 0
;;
   l)
LISTONLY=true
QUIET=true
;;
   q)
QUIET=true
;;
   r)
RECURSIVE=true
;;
   L)
SHOWLEFT=true
;;
   R)
SHOWRIGHT=true
;;
   T)
IGNORETEXT=true
;;
   X)
IGNOREEXIST=true
;;
   \?)
echo "$BADUSAGE" >&2
exit 1
;;
   esac
done
shift `expr $OPTIND - 1`

if [ $# -ne 2 ]; then
   echo "$BADUSAGE" >&2
   exit 1
elif [ ! -d "$1" ]; then
   echo "Invalid directory: $1" >&2
   echo "$BADUSAGE" >&2
   exit 1
elif [ ! -d "$2" ]; then
   echo "Invalid directory: $2" >&2
   echo "$BADUSAGE" >&2
   exit 1
fi

cdir=`pwd` # current directory
cd "$2"
rdir=`pwd` # right directory
cd "$cdir"
cd "$1"
ldir=`pwd` # left directory

if [ "$ldir" = "$rdir" ]; then
   exit 0
fi

NODIRS=`(for name in $EXCLUDE_DIRLIST; do
   find "$ldir" -name "$name" -type d -print | sed "s;^$ldir/;;"
   find "$rdir" -name "$name" -type d -print | sed "s;^$rdir/;;"
done) | sort | uniq`

if $RECURSIVE; then
   (
find "$ldir" -type f -print | sed "s;^$ldir/;;"
find "$rdir" -type f -print | sed "s;^$rdir/;;"
   ) | sort | uniq >"$FILELIST"
else
   (
'ls' -a1 "$ldir" | while read f; do
    if [ ! -d "$ldir/$f" ]; then
        echo "$f"
    fi
done
'ls' -a1 "$rdir" | while read f; do
    if [ ! -d "$rdir/$f" ]; then
        echo "$f"
    fi
done
   ) | sort | uniq >"$FILELIST"
fi

while read f; do
   if [ -n "$EXCLUDE_LIST" ]; then
doexclude=false
for exclude in $EXCLUDE_LIST; do
    if [ "`basename \"$f\"`" = "$exclude" ]; then
 doexclude=true
 break
    fi
done
if $doexclude; then
    continue
fi
   fi

   if [ -n "$NODIRS" ]; then
       doexclude=false
       for dir in $NODIRS; do
           quit=`expr "$f" : "$dir"`
           if [ $quit -gt 0 ]; then
               doexclude=true
               break
           fi
       done
       if $doexclude; then
    continue
       fi
   fi

   lfile="$ldir/$f"
   rfile="$rdir/$f"
   if [ -f "$lfile" ]; then
if [ -f "$rfile" ]; then
    if file "$lfile" | grep "text\$" >/dev/null; then
 if file "$rfile" | grep "text\$" >/dev/null; then
     if $IGNORECR; then
  lfile=/tmp/$SCRIPT.lfile$$
  sed "s;
*$;;" "$ldir/$f" >"$lfile"
  rfile=/tmp/$SCRIPT.rfile$$
  sed "s;
*$;;" "$rdir/$f" >"$rfile"
     fi
     if $QUIET; then
  diff $DIFFOPTS "$lfile" "$rfile" >"$DIFFS"
  if [ -s "$DIFFS" ]; then
      if $LISTONLY; then
   echo "$f"
      else
   echo "FILE: $f"
   cat "$DIFFS"
      fi
  fi
     else
  echo "FILE: $f"
  diff $DIFFOPTS "$lfile" "$rfile"
     fi
     if $IGNORECR; then
  rm -f "$lfile" "$rfile"
     fi
 else
     if $IGNORETEXT; then
  continue
     elif $LISTONLY; then
  echo "$f"
     else
  echo "FILE: $f is not a text file in $rdir"
     fi
 fi
    elif file "$rfile" | grep "text\$" >/dev/null; then
 if $IGNORETEXT; then
     continue
 elif $LISTONLY; then
     echo "$f"
 else
     echo "FILE: $f is not a text file in $ldir"
 fi
    elif $BINARY; then
 if $QUIET; then
     cmp $CMPOPTS "$lfile" "$rfile" >"$DIFFS"
     if [ -s "$DIFFS" ]; then
  if $LISTONLY; then
      echo "$f"
  else
      echo "FILE: $f"
      cat "$DIFFS"
  fi
     fi
 else
     echo "FILE: $f"
     cmp $CMPOPTS "$lfile" "$rfile"
 fi
    fi
else
    if $IGNOREEXIST; then
 continue
    elif $LISTONLY; then
 echo "$f"
    else
 echo "FILE: $f does not exist in $rdir"
 if $SHOWLEFT; then
     if file "$lfile" | grep "text\$" >/dev/null; then
  cat "$lfile" | sed "s;^;<;;"
     fi
 fi
    fi
fi
   else
if $IGNOREEXIST; then
    continue
elif $LISTONLY; then
    echo "$f"
else
    echo "FILE: $f does not exist in $ldir"
    if $SHOWRIGHT; then
 if file "$rfile" | grep "text\$" >/dev/null; then
     cat "$rfile" | sed "s;^;>;;"
 fi
    fi
fi
   fi
done <"$FILELIST"

rm -f "$FILELIST" "$DIFFS"

exit 0



Thanks Ragnar for this easy to use script !



Bruno


-- Apr 26 2005 ( Revised Dec 10 2005 ) --


Tips Linux Explorers   All Things Linux Forum   Great Linux Links   LinuxClues.com   Hometown