Bourne Shell Case Study I..

Case Study - Who has what??

Sometimes it is necessary to find out the difference between two files of data. We recently encountered this problem when we needed to "see" if two NT servers were in sync. We needed to know which dlls were loaded on one system and not the other. We also needed to know if the version of loaded dlls was the same.

The NT administrator created two files nts001.txt and nts002.txt that had a list of dlls. The basic layout of the files was :

$ head nts001.txt
ACCWIZ.DLL      8.0.0.3432,     11/17/96 0:00,  123392, No ,    8.0.0.3432
ACLEDIT.DLL     4.0.1381.4,     5/1/97 0:00,    135952, No ,    4.0.1381.4
ADME.DLL        1997.1.8.205,   1/11/97 23:00,  57856,  No ,    1.0.0.205
ADVAPI32.DLL    4.0.1381.4,     5/1/97 0:00,    246544, Yes,    4.0.1381.4
ALRSVC.DLL      4.0.1374.1,     8/9/96 1:30,    23312,  No ,    4.0.1374.1
AMDDLG.DLL      4.0.1371.1,     8/9/96 1:30,    9488,   No ,    4.0.1371.1
AMDNCDET.DLL    4.0.1371.1,     8/9/96 1:30,    12560,  No ,    4.0.1371.1
ASPPERF.DLL     1.0.0.0,        12/6/96 14:58,  8192,   Yes,    1.0.0.0
ASYCFILT.DLL    2.20.4118.1,    5/1/97 0:00,    118544, No ,    2.20.4118.1
AVICAP.DLL      1.15.0.1,       8/9/96 1:30,    69584,  No ,    1.15.0.1

The fields are separated by tabs, The first field is the dll name and the second is the level number. We are only interested in lines where the the dll is loaded indicated by the Yes.


  1. The first step is to extract the "Yes" lines. This is best done with grep like:
    $ grep 'Yes' Afile >Afile.l
    ADVAPI32.DLL    4.0.1381.4,     5/1/97 0:00,    246544, Yes,    4.0.1381.4
    ASPPERF.DLL     1.0.0.0,        12/6/96 14:58,  8192,   Yes,    1.0.0.0
    AVIFIL32.DLL    4.0.1371.1,     8/9/96 1:30,    86800,  Yes,    4.0.1371.1
    COMCTL32.DLL    4.70.1147.1,    5/1/97 0:00,    310032, Yes,    4.70.1147.1
    COMDLG32.DLL    4.0.1381.4,     5/1/97 0:00,    185104, Yes,    4.0.1381.4
    DDEML.DLL       3.50.0.103,     8/9/96 1:30,    39936,  Yes,    3.50.0.103
    FTPCTRS2.DLL    4.0.1371.1,     8/9/96 1:30,    8976,   Yes,    4.0.1371.1
    FTPSAPI2.DLL    4.0.1371.1,     8/9/96 1:30,    11536,  Yes,    4.0.1371.1
    


  2. Now to see if the dlls in file 1 are also in file 2 we need a list of the dlls. We can get the list using cut.
    $ dll=`cut -f1 Afile.l`
    $ echo $dll | head -3
    ADVAPI32.DLL 
    ASPPERF.DLL 
    AVIFIL32.DLL
    



  3. Now "is an item in our dll variable list not in the second file"? To do this we need a loop to look at the entries and grep like:
    for x in $dll
    do
     if grep  $x $Bfile.l >/dev/null
     then
        :
     else
        grep $x $Afile.l
     fi
    done
    
    
    DBNMPNTW.DLL    1997.4.2.0,     6/16/97 0:00,   23552,  Yes,    6.50.2.52
    GDAPI.DLL       4.0.1377.1,     8/9/96 1:30,    11024,  Yes,    4.0.1377.1
    
    We can use this basic approach to locate items in one file not in the other file.


  4. Now we need to find out if a dll is in both files, then is the level the the same?. Once again we will pull our list with the variable name as is 2. Then find a match in file two. Extract the version level from file1. If it is the same ok, else report the result.
    sl=`cut -f1 Afile.l`
    for x in $sl
    do
    if grep  $x Bfile.l >tmp$$
    then
        v=`grep $x Afile.l | cut -f2`
        if grep $v tmp$$ >/dev/null
        then
          :
        else
         echo
         echo "Afile: " `grep $x Afile.l
         echo "Bfile: " `grep $x Bfile.l
         echo
        fi
    fi
    done
    



  5. Putting all of the pieces together we get:
    #!/bin/sh
    a=$1                              # File A
    b=$2                              # File B
    #
    # extract the loaded dlls create a .l file
    #
    grep 'Yes' $a >$a.l               # File A Loaded
    grep 'Yes' $b >$b.l               # File B loaded
    #
    # find items in file A not in file B
    #
    echo
    echo "The following DLLs are on $a but not $b"
    echo
    sl=`cut -f1 $a.l  `                  # get the list
    for x in $sl                         # go through each item in list
    do
       if grep  $x $b.l >/dev/null    # in file B?
       then
           :                             # ok do nothing
       else
           grep $x $a.l                  # not found list entry in file 1
       fi
    done
    #
    # Now find items in file B not in file A
    #
    echo
    echo "The following DLLs are on $b but not $a"
    echo
    sl=`cut -f1 $b.l  `                  # get the list
    for x in $sl                         # go through each item in list
    do
       if grep  $x $a.l >/dev/null    # in file A?
       then
           :                             # ok do nothing
       else
           grep $x $b.l                  # not found list entry in file 2
       fi
    done
    #
    # Now find same dlls with differnt versions
    #
    echo
    echo "Different versions of DLLs on $a and $b"
    echo
    sl=`cut -f1 $a.l`                     # get a list of dlls
    for x in $sl                          # go through each item in list
    do
    if grep  $x $b.l >tmp$$            # Match in file B save result 
    then
        v=`grep $x $a.l | cut -f2`        # get version # from file A
        if grep $v tmp$$ >/dev/null    # same as saved info?
        then
          :                               # yes do nothing
        else
         echo
         echo "$a: " `grep $x $a.l`       # no show both entries
         echo "$b: " `grep $x $b.l`
         echo
        fi
    fi
    done
    #
    # cleanup
    #
    rm tmp$$
    rm $a.l
    rm $b.l
    


  6. Running this script prodcues the following:
    $ diffnt nts001.txt nts002.txt
    
    The following DLLs are on nts001.txt but not nts002.txt
    
    HTICONS.DLL     4.0.1381.4,     5/1/97 0:00,    25360,  Yes,    4.0.1381.4
    
    The following DLLs are on nts002.txt but not nts001.txt
    
    DBNMPNTW.DLL    1997.4.2.0,     6/16/97 0:00,   23552,  Yes,    6.50.2.52
    GDAPI.DLL       4.0.1377.1,     8/9/96 1:30,    11024,  Yes,    4.0.1377.1
    GDCTRS.DLL      4.0.1377.1,     8/9/96 1:30,    9488,   Yes,    4.0.1377.1
    MSVCIRT.DLL     4.20.0.6201,    8/9/96 1:30,    74752,  Yes,    4.20.0.6201
    MSVCRT40.DLL    4.2000.0.6172,  8/9/96 1:30,    65024,  Yes,    4.20.0.6172
    NTWDBLIB.DLL    1997.4.2.0,     6/16/97 0:00,   276480, Yes,    6.50.2.52
    PRINTUI.DLL     4.0.1381.4,     5/1/97 0:00,    181520, Yes,    4.0.1381.4
    SHLWAPI.DLL     4.70.0.1215,    3/22/97 12:44,  37376,  Yes,    4.70.0.1215
    WINSCTRS.DLL    4.0.1371.1,     8/9/96 1:30,    10000,  Yes,    4.0.1371.1
    WINSRPC.DLL     4.0.1381.3,     5/1/97 0:00,    15120,  Yes,    4.0.1381.3
    WSHTCPIP.DLL    4.0.1381.4,     5/1/97 0:00,    18704,  Yes,    4.0.1381.4
    
    Different versions of DLLs on nts001.txt and nts002.txt
    
    
    nts001.txt:  MSVCRT.DLL 4.20.0.6201, 8/9/96 1:30, 267536, Yes, 4.20.0.6201
    nts002.txt:  MSVCRT.DLL 5.0.0.7022, 1/22/97 23:07, 271632, Yes, 5.0.0.7022
    
    
    nts001.txt:  URL.DLL 4.40.1371.1, 8/9/96 1:30, 133392, Yes, 4.40.1371.1
    nts002.txt:  URL.DLL 4.70.0.1215, 3/22/97 12:44, 103184, Yes, 4.70.0.1215
    
    

    © Allan Kochis Last revision 1/3/2000