1#!/bin/tcsh
2
3set prog = `basename $0`
4
5if ( $#argv < 2 ) then
6    goto SHOW_HELP
7endif
8
9set do_diffs  = 1
10set ignore_missing = 0
11set showfiles = 1
12set showdiffs = 0
13set showlcomp = 0
14set savediffs = 0
15set verb      = 1
16set xxdiff    = 0
17set diffopts  = ()
18
19set skip_data = 0 # skip BRIK, dcm
20set ignore_list = ( )
21
22set narg = 1
23@   amax = $#argv - 2
24while ( $narg <= $amax )
25    if ( "$argv[$narg]" == "-quiet" ) then
26        set verb = 0
27    else if ( "$argv[$narg]" == "-ignore_append" || \
28              "$argv[$narg]" == "-ia" ) then
29        @ narg ++
30        set ignore_list = ( $ignore_list `echo $argv[$narg]` )
31    else if ( "$argv[$narg]" == "-ignore_list" || \
32               "$argv[$narg]" == "-il" ) then
33        @ narg ++
34        set ignore_list = ( `echo $argv[$narg]` )
35    else if ( "$argv[$narg]" == "-ignore_missing" || \
36              "$argv[$narg]" == "-im" ) then
37        set ignore_missing = 1
38    else if ( "$argv[$narg]" == "-save" ) then
39        set savediffs = 1
40    else if ( "$argv[$narg]" == "-no_diffs" ) then
41        set do_diffs = 0
42    else if ( "$argv[$narg]" == '-diff_opts' ) then
43        @ narg ++
44        set diffopts = ( $diffopts $argv[$narg] )
45    else if ( "$argv[$narg]" == "-show" ) then
46        set showdiffs = 1
47        set showfiles = 0
48    else if ( "$argv[$narg]" == "-show_list_comp" ) then
49        set showlcomp = 1
50    else if ( "$argv[$narg]" == "-skip_data" ) then
51        set skip_data = 1
52    else if ( "$argv[$narg]" == "-verb" ) then
53        @ narg ++
54        set verb = $argv[$narg]
55        if ( $verb > 2 ) then
56            set echo
57        endif
58    else if ( "$argv[$narg]" == "-xxdiff" ) then
59        set xxdiff    = 1
60        set showdiffs = 1
61        set showfiles = 0
62    else if ( "$argv[$narg]" == "-X" ) then
63        set xxdiff    = 1
64        set showdiffs = 1
65        set showfiles = 0
66        set ignore_missing = 1
67    else
68        goto SHOW_HELP
69    endif
70    @ narg ++
71end
72
73# if xxdiff is requested, make sure it exists...
74if ( $xxdiff ) then
75   which xxdiff >& /dev/null
76   if ( $status ) then
77      echo "** missing Unix program xxdiff, please install and try again"
78      exit
79   endif
80endif
81
82# default to pdf output, but use ps if ps2pdf is not there
83set useps = 0
84which ps2pdf >& /dev/null
85if ( $status ) then
86    set useps = 1
87endif
88
89# if ignore_list, make compund grep expression
90set iglist = ( )
91foreach istr ( $ignore_list )
92   set iglist = ( $iglist -e $istr )
93end
94
95# we should have 2 directories yet to come
96if ( $#argv <= $narg ) then
97   echo ""
98   echo "** options should be followed by 2 directory names"
99   if ( $#argv == $narg ) then
100      echo "   have only one ($argv[$narg])"
101   else
102      echo "   have neither"
103   endif
104   echo ""
105   exit 1
106else if ( ! -d "$argv[$narg]" ) then
107   echo "** last 2 args expected to be directories, but '$argv[$narg]' is not"
108   exit 1
109endif
110
111# set the new and old dirs
112set ndir = $argv[$narg]
113@ narg ++
114set odir = $argv[$narg]
115
116# new files
117cd $ndir
118if ( $#ignore_list > 0 ) then
119   set new_files = ( `find . -type f | grep -v $iglist | cut -b3- | sort` )
120else
121   set new_files = ( `find . -type f | cut -b3- | sort` )
122endif
123cd -
124
125# old files
126cd $odir
127if ( $#ignore_list > 0 ) then
128   set old_files = ( `find . -type f | grep -v $iglist | cut -b3- | sort` )
129else
130   set old_files = ( `find . -type f | cut -b3- | sort` )
131endif
132cd -
133
134set use_files = ()
135# are the lists of names identical?
136set identical = 0
137if ( $#new_files == $#old_files ) then
138   set identical = 1
139   foreach index ( `count -digits 1 1 $#new_files` )
140      if ( $new_files[$index] != $old_files[$index] ) then
141         set identical = 0
142         break
143      endif
144   end
145endif
146
147# maybe the user wants to see the list comparison
148# (if user wants it, but it is not appropriate, let them know why)
149if ( $showlcomp ) then
150   if ( $identical ) then
151      if ( $verb > 1 ) echo "-- showcomp: lists are identical"
152      exit 0
153   else if ( $#new_files != $#old_files ) then
154      echo "-- showcomp: no pairwise list difference"
155      echo "           : ignoring -show_list_comp"
156      echo ""
157      set showlcomp = 0
158   endif
159endif
160
161set ndiffs = 0
162if ( ! $identical && ($#new_files == $#old_files)  \
163                  && ( $showlcomp || ($verb > 1) ) ) then
164   if ( ! $showlcomp ) then
165      echo ""
166      echo "++ pairwise file name comparison:"
167      echo ""
168   endif
169   foreach index ( `count -digits 1 1 $#new_files` )
170      if ( $new_files[$index] != $old_files[$index] ) then
171         @ ndiffs += 1
172         printf "%30s  vs.  %-30s\n" $new_files[$index] $old_files[$index]
173      endif
174   end
175   if ( $showlcomp ) then
176      if ( $verb > 1 ) echo "-- found $ndiffs diffs"
177      exit 0
178   endif
179   echo ""
180endif
181
182
183if ( ! $identical ) then
184    echo different file lists found: $#new_files vs. $#old_files
185    # okay, where is the difference ?
186    foreach file ( $new_files )
187        if ( $ignore_missing ) then
188           set use_files = ( $use_files $file )
189        else if ( ! -f $odir/$file ) then
190           echo extra new file: $ndir/$file
191        endif
192    end
193    foreach file ( $old_files )
194        if ( ! $ignore_missing && ! -f $ndir/$file ) then
195           echo extra old file: $odir/$file
196        endif
197    end
198    if ( ! $ignore_missing ) then
199       exit
200    else if ( $#use_files < 1 ) then
201       echo "** no common files left to compare"
202       exit
203    endif
204
205    echo ""
206endif
207
208if ( $verb > 1 ) echo "-- comparing $#new_files files..."
209
210if ( ! $do_diffs ) exit
211
212if ( $savediffs ) then
213    if ( -d diffs ) then
214        echo removing old diff files...
215        \rm -f diffs/* >& /dev/null
216    endif
217    mkdir diffs
218    if ( $status ) then
219        echo failed to make diffs dir, exiting...
220        exit
221    endif
222endif
223
224set count = 0
225foreach file ( $new_files )
226  # skip files that we don't want to spend time on
227  if ( $skip_data &&  \
228        ( $file =~ *.BRIK || $file =~ *.BRIK.gz || $file =~ *.dcm || \
229          $file =~ *.nii  || $file =~ *.nii.gz ) ) continue
230
231  if ( $showdiffs ) then
232    diff $diffopts $ndir/$file $odir/$file >& /dev/null
233    set ss = $status
234    if ( $ss ) then
235      if ( $verb ) then
236         echo "------------------------------------------------------------"
237         echo "--- $file ---"
238         echo ""
239      endif
240      if ( $xxdiff ) then
241         xxdiff $ndir/$file $odir/$file
242      else
243         diff $diffopts $ndir/$file $odir/$file
244      endif
245    endif
246  else
247      diff $diffopts $ndir/$file $odir/$file >& /dev/null
248      set ss = $status
249  endif
250  if ( $ss ) then
251    if ( $showfiles ) echo "    $ndir/$file"
252    @ count ++
253
254    if ( $savediffs ) then
255      set dfile = `echo $file | sed 's/\//./g'`
256      diff $diffopts $ndir/$file $odir/$file > diffs/t.$dfile.txt
257
258      if ( $useps ) then
259          diff -bB $odir/$file $ndir/$file | diffpp $odir/$file \
260                   | enscript -Ge -p diffs/d.$dfile.ps
261          if ( $status ) then
262             echo "** failed -save diffs, exiting"
263             exit
264          endif
265      else
266          diff -bB $odir/$file $ndir/$file | diffpp $odir/$file \
267                   | enscript -Ge -p - | ps2pdf - > diffs/d.$dfile.pdf
268          # if ( $status ) then
269          if ( -z diffs/d.$dfile.pdf ) then
270             echo "** failed -save diffs, exiting"
271             exit
272          endif
273      endif
274    endif
275  else if ( $verb > 1 && $showfiles ) then
276    echo "-- no diffs for $file"
277  endif
278end
279
280if ( $verb > 1 || ! $showfiles ) then
281    if ( $count > 0 ) echo ""
282    if ( $verb ) echo $count file diffs found
283endif
284
285exit
286
287SHOW_HELP:
288cat << EOF
289
290   ----------------------------------------------------------------------
291   $prog - show file differences between 2 directories
292
293      Given: 2 directory names
294
295      If desired, list files that do not exist in one of the directories.
296      For the files that exist in both directories, list those that differ.
297      If desired, show the actual differences.
298
299      This is similar to @diff.files, which only looks at files in a
300      specified list.
301
302   ----------------------------------------------------------------------
303   usage: $prog [OPTIONS] new_dir old_dir"
304
305   ----------------------------------------------------------------------
306   options:
307
308      -diff_opts 'OPTS'      : apply OPTS as options in diff commands
309      -ignore_append i1 ...  : append to ignore_list (list in quotes)
310      -ia                    : short for -ignore_append
311      -ignore_list i1 ...    : create new ignore_list (list in quotes)
312      -il                    : short for -ignore_list
313      -ignore_missing        : only compare overlapping files
314                               If different files, fail.
315      -no_diffs              : only compare existence of files
316      -quiet                 : only list files with diffs
317      -save                  : save actual file differences (txt and pdf)
318      -show                  : show actual file differences
319      -show_list_comp        : show any pairwise differences in file lists
320                               (terminate after showing comparison)
321      -skip_data             : skip binary diff of select data files
322                               (.BRIK, .dcm, .BRIK.gz)
323      -verb LEVEL            : set verbosity level (0,1,2)
324                               (default 1)
325      -xxdiff                : use xxdiff to show diffs
326      -X                     : implies -xxdiff -ignore_missing
327
328
329   ----------------------------------------------------------------------
330   examples:
331
332        @diff.tree here/this.dir ../../../there/that.dir
333        @diff.tree -show_list_comp test1/FT/SUMA test2/FT/SUMA
334
335   ----------------------------------------------------------------------
336   R Reynolds    written ages ago, but added 10 Jun, 2015
337   ----------------------------------------
338    
339EOF
340
341