DirDiff

Purpose:

A directory comparison utility written in Tcl/Tk.

DirDiff is a graphical tool to display the differences between files in directories. Given two or more directory trees (the program can handle up to 5 individual directories at the same time), dirdiff will display the differences between them in various colors.

The program is a combination of dirdiff (directory comparison) as well as tkdiff (file comparison).

  • It depends on the diff command - a unix utility command.
  • For the moment, diff.exe needs to be available in the same directory as dirdiff.exe.
  • If you need support for a different operating system, please use the comment section below.

The program is especially useful for:

  • file and directory maintenance to sort out redundant information (various instances of source files),
  • data synchronization when working over a VPN network, to find out differences in your local copy of a replicated directory tree.

DirDiff works best with text files, but can also be used to compare any kind of file (to compare file time-stamp and file size).

  • If a file has a binary format, be aware that the tkdiff (file comparison sub-command) is not applicable (or at least does not make sense).

Modification installation notes:

The original DirDiff utility program has been updated to work with the latest software release (tcl/tk 8.6) and has been slightly extended with a more user friendly file selection dialog which is drag&drop enabled.

Furthermore the software does not need to be installed, just drop it somewhere in your PATH environment. There is only one more dependency which is the diff.exe comparison utility which also needs to be copied the same way as the main program.

Dirdiff instructions:

  • Dirdiff compares all the files in up to five directories.

    directories.png

    You can use the Browse.. button or just drag and drop a directory onto one of the entry fields with the file-explorer.

  • There is one column in the main window for each directory.

    dialogwindow.png

  • Each file is shown with a colored square indicating its status.

    Files are like leaves on a deciduous tree: the newest ones are green, and then they turn yellow, orange, and red as they get older.

    leaves.png

  • Double-click a file to show differences between two versions.

    By default, the first and last versions are compared, but this can be changed by the ‘Diff’ menu in the main window.

  • You can select several files to copy or to make a patch by shift-clicking.

  • You can search for a file by typing part of its name in the entry and pressing the <Return> key.

  • In the diff window, check the boxes on the left margin for changes you want to preserve, and then choose ‘Merge’ to move those changes into one of the files.

    Alternatively, choose ‘Copy’ in the main window to copy across the whole file, replacing any changes.

  • Make patch produces a file describing the changes between the files that can be applied by the patch tool.

    • You can edit the patch before saving, and may wish to add explanatory text, instructions, or patch(1) Prereq lines at the beginning.

    • To save the patch, enter a filename in the patch window relative to the current directory, and choose Save. This will also close the window.

Sending out patches:

  • If you are sending out patches, then the “from” directory should be the original version of the source.

  • Try to make sure that the two files have the same number of leading directories.

    See the patch(1) man page for more information.


Credits:

Dirdiff:

Copyright (C) 1999-2004 Paul Mackerras. All rights reserved.

This program is free software; it may be used, copied, modified and distributed under the terms of the GNU General Public Licence, either version 2, or (at your option) any later version.

TkDiff:

Autohor: John C. Quillan
Contributors: Ulrich Lauther, Michael J. Long
Copyright (C) 1996 John C. Quillan

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

Various modifications made + executable for various platforms provided by me.

Change history:

# -----------------------------------------------------------------------------
# Change history:
# 15-09-30, hans: various modifications + required changes for FileManager
#                 integration implemented, mainly for drag&drop.
#
# 20-10-23, hans: safedefault to remember previous selection added,
#                 + some minor GUI improvements (file selection) added
# -----------------------------------------------------------------------------

The software can be downloaded from the following link:

File name:Size / byte:
DirDiff.zip4016191

Solving a problem: mtime - offset due to time shift

When using DIRDIFF for file comparison, I discovered a mismatch in the time-stamp of the same file stored locally on the disc and remotely on the server. Except the time-stamp, files were otherwise identical.

In our case the time-stamp is meant to be the “last modified date” of a file.

The offset was exactly 1 hour, probably caused by the time shift between European summer and winter time setting.

I did not want to use DIRDIFF to synchronize files but instead use a small script to correct the time-stamp locally (similar to the UNIX touch command). This way the usage of unnecessary network bandwidth could be avoided.

With the following code, this kind of problem can be solved:

The following tcl-tk script takes a directory as an argument (hard coded) and traverses down this directory to collect all the files available.

Within the foreach loop the file mtime is used in combination with the **clock"" command to update the timestamp for each individual file.

The code might be fine tuned for one or the other purpose like a more user friendly “file selection dialog” or “filter options” to exclude directories…

# --- change_mtime_plus_one_hour.tcl
# -----------------------------------------------------------------------------
# (c) 2023, Johann Oberdorfer - Engineering Support | CAD | Software
#     johann.oberdorfer [at] gmail [dot] com
#     www.johann-oberdorfer.eu
# -----------------------------------------------------------------------------
# This source file is distributed under the BSD license.
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#   See the BSD License for more details.
# -----------------------------------------------------------------------------
# Purpose:
#   When using DIRDIFF for file comparison, I discovered a mismatch
#   in the time-stamp of the same file stored locally and remotely on a server.
#   In our case the time-stamp is meant to be the "last modified date"
#   of a file. The offset was exactly 1 hour probably caused by the time shift
#   between European summer and winter time setting - arrr....
#
#  Usage:
#    Attention:
#    - directory is hard coded!
#    - run the script only once
#    - mtime changes can be reverted by specifying [clock add $tm -1 hours]
# -----------------------------------------------------------------------------
# Rev. History: 23-09-07, Hans
# -----------------------------------------------------------------------------

# prove of concept:
#   https://stackoverflow.com/questions/29756493/add-1440-minutes-from-current-timestamp-in-tcl
#   set fname "my-test-file.txt"
#   set tm [file mtime $fname]
#   set tm_new [clock add $tm 1 hours]
#   puts "$tm : [clock format $tm]"
#   puts "$tm_new : [clock format $tm_new]"

proc GetFiles { dir pattern } {
	variable excluded_dirnames

	set file_list {}

	# fix the directory name...
	set basedir [string trimright [file join [file normalize $dir] { }]]

	# search in the current directory for matching files...
	foreach fname [glob -nocomplain -type {f r} -path $basedir $pattern] {
		lappend file_list $fname
	}

	# now search for any sub directories in the current directory...
	foreach dir_name [glob -nocomplain -type {d r} -path $basedir "*"] {

		# recursive call ...
		set subdir_list [GetFiles $dir_name $pattern]

		if { [llength $subdir_list] > 0 } {
			foreach fname $subdir_list {
				lappend file_list $fname
			}
		}
	}

	return $file_list
}

# here we go ...
# set dir [file dirname [info script]]

package require Tk
catch {console show}

# -----------------------------------------------------
# configuration section
# -----------------------------------------------------
set project_dir [file join "X:/project/current_dir"]
set pattern "*.*"
# -----------------------------------------------------

# get all files ...

set rlist [GetFiles	$project_dir $pattern ]

puts "File mtime change summary: "
puts ""
				
set cnt 0
set fcnt [llength $rlist]				

foreach f $rlist {

	set fp [open $f "r"]

	set tm [file mtime $f]
	set tm_new [clock add $tm 1 hours]
	# set tm_new [clock add $tm -1 hours] ;# a possible option
	
	# -------------------
	file mtime $f $tm_new
	#--------------------

	puts "${cnt}/${fcnt} $f  [clock format $tm] => [clock format $tm_new]"

	incr cnt
	update
}

puts ""
puts "Done."