Doug Smith
Doug Smith

Reputation: 29326

How do I compare the contents of all the files in a directory against another directory?

I have a directory with a bunch of C files, .c and .h, and another very similar directory of files that a coworker has sent that have very minor differences, due to an update, and I'd like to see what those differences are.

I could run a diff on every file manually, but as they're named the same is there anyway I could do it quicker and easily see which files are different and what makes them different?

Upvotes: 1

Views: 342

Answers (2)

Jonathan Leffler
Jonathan Leffler

Reputation: 755054

You may find there's a command dircmp on your machine that will do the job of comparing two directories. It identifies the files found only in the first directory and the files found only in the second directory. For files found in both, it tells you whether they're the same or different.

If you don't have one as standard on the machine, you can use this one instead:

#!/bin/sh
#
#   @(#)$Id: dircmp.sh,v 1.6 2003/03/12 08:29:13 jleffler Exp jleffler $
#
#   Simulation of the much-loved dircmp(1) script, with extensions.

arg0=$(basename $0 .sh)

error(){
    echo "$arg0: $*" 1>&2
    exit 1
}

dflag=0 # Files that are different
mflag=0 # Files that are missing in one or the other
sflag=0 # Files that are the same in both (or directories, or otherwise special)
while getopts dms flag
do
    case "$flag" in
    (d) dflag=1;;
    (m) mflag=1;;
    (s) sflag=1;;
    (*) echo "Usage: $arg0 [-dms] dir1 dir2" 1>&2; exit 1;;
    esac
done
shift $(expr $OPTIND - 1)

# If user set no flags, set them all (traditional behaviour of dircmp).
if [ $sflag = 0 ] && [ $dflag = 0 ] && [ $mflag = 0 ]
then dflag=1; mflag=1; sflag=1
fi

if [ $# != 2 ]
then echo "Usage: $arg0 [-dms] dir1 dir2" 1>&2; exit 1
elif [ ! -d "$1" ]
then error "$1 is not a directory"
elif [ ! -d "$2" ]
then error "$2 is not a directory"
fi

tmp="${TMPDIR:-/tmp}/dc.$$"
trap "rm -f \"$tmp\".?; exit 1" 0 1 2 3 13 15

(cd "$1" 1>&2 && find . -print | sort) > "$tmp".1
(cd "$2" 1>&2 && find . -print | sort) > "$tmp".2

{
if [ $mflag = 1 ]
then
    comm -23 "$tmp".1 "$tmp".2 > "$tmp".3
    comm -13 "$tmp".1 "$tmp".2 > "$tmp".4
    if [ -s "$tmp".3 ] || [ -s "$tmp".4 ]
    then
        long=$(awk '{if(length($0) > len) { len = length($0); }}
                END { print 2 * len + 6; }' "$tmp".3 "$tmp".4)
        echo "Files in $1 only and in $2 only"
        echo
        pr -w$long -l1 -t -m "$tmp".3 "$tmp".4
        echo
    fi
    rm -f "$tmp".3 "$tmp".4
fi

if [ $sflag = 1 ] || [ $dflag = 1 ]
then
    comm -12 "$tmp".1 "$tmp".2 > "$tmp".5
    if [ -s "$tmp".5 ]
    then
        case $sflag$dflag in
        (11) echo "Comparison of files in $1 and $2";;
        (01) echo "Files which differ in $1 and $2";;
        (10) echo "Files which are the same in $1 and $2";;
        esac
        echo
        cat "$tmp".5 |
        while read file
        do
            if [ -f "$1/$file" ] && [ -f "$2/$file" ]
            then
                if cmp -s "$1/$file" "$2/$file"
                then [ $sflag = 1 ] && echo "same                $file"
                else [ $dflag = 1 ] && echo "different           $file"
                fi
            elif [ $sflag = 0 ]
            then continue
            elif [ -d "$1/$file" ] && [ -d "$2/$file" ]
            then echo "directory           $file"
            elif [ -b "$1/$file" ] && [ -b "$2/$file" ]
            then echo "block special       $file"
            elif [ -c "$1/$file" ] && [ -c "$2/$file" ]
            then echo "character special   $file"
            elif [ -p "$1/$file" ] && [ -p "$2/$file" ]
            then echo "named pipe          $file"
            else echo "***dubious***       $file"
            fi
        done
        echo
    fi
fi
} |
uniq

rm -f $tmp.?
trap 0

Upvotes: 0

jherran
jherran

Reputation: 3367

diff command is able do it. Just try:

diff directory1 directory2

Upvotes: 2

Related Questions