tdiff − tree diff, list differences between various inode attributes ( stat(2) structure) and contents for two directory trees
tdiff [OPTIONS]... DIRECTORY1 DIRECTORY2
List differences between DIRECTORY1 and DIRECTORY2 file trees, comparing any of the inode attributes, also known as stat(2) structure members. Inode attributes are:
• |
file type (regular file, directory, FIFO, socket, etc.), |
|||
• |
file size, |
|||
• |
file block count (physical storage size), |
|||
• |
owner uid and gid, |
|||
• |
access, modification and inode change times, |
|||
• |
the set of hard links a file has, |
|||
• |
extended attributes (if supported), |
|||
• |
ACLs (if supported), |
|||
• |
file system flags (BSD UFS, MacOSX). |
By default, tdiff reports differences in any file contents or attributes except for the various file times. The set of attributes to be checked can be modified with the various options.
Beyond inode attribute checks, tdiff can check (and will check by default) regular files for contents difference. Optionally, tdiff can use an external program to determine if the files are considered to be different. See the −x/−−exec, −w/−−exec−always, and −W/−−exec−always−diff options.
−h, −−help
Show a short help message and exit.
−v, −−verbose
Increase verbosity. Four cumulative levels of logging verbosity are supported:
-v |
report overall statistics: total number of files scanned, compared, etc. | ||
-vv |
report if any files are skipped, and for what reason (exclusion, already compared, etc.) | ||
-vvv |
report internal data structure statistics. | ||
-vvvv |
report memory statistics (if available on your system). |
−V, −−version
Show the tdiff version
information, compiled-in features and flags (if any) then
exit.
The compiled-in feature list shows which features
tdiff has been compiled with: O_NOATIME, flags, acl,
and xattr support, acl optimization (acl_cmp), the
readdir(2) implementation used, the file system time
granularity (either seconds (s) or nanoseconds
(ns)) and if comparing symbolic links will update
their access time (readlink=readlink) or not
(readlink=open(O_PATH|O_NOFOLLOW)+readlinkat).
If flags support is compiled in, the list of recognized
flags will be listed as well.
The single-letter toggle options come in two versions, upper-case and lower-case. The lower-case option enables the the attribute check, while the upper-case option disables it.
The long toggle
options are named after the stat(2) structure names:
for example, −−mtime is used to check the
st_mtime stat(2) structure member, which is
the file modification time. Similarly to short toggle
options, long toggle options have a
−−no− version to turn off the
equivalent check (eg. −−no−mtime).
−b, −−blocks
Report file block count
differences (st_blocks) except for directories which
are ignored.
This is on by default.
−B, −−no−blocks
Do not report file block count differences.
−c, −−contents
Report file content
differences for regular files and symbolic links.
For regular files, their contents are compared and any
discrepancies are reported as a contents difference.
For symbolic links, a difference will be reported if their
targets differ.
See the CONTENTS COMPARISONS section below for the
exact semantics.
This is on by default.
−C, −−no−contents
Do not report file content differences.
−d, −−dirs
Diff directory contents:
report if any file is present in only one directory.
This is on by default.
−D, −−no−dirs
Do not diff directory contents: files only present in a single directory are not reported.
−e, −−hardlinks
Report any differences in the
set of hard links a file may be linked to.
For example if in a directory two files are hard linked
together while in the other directory, they are not,
tdiff will report that the files are hard links only
in the first directory.
tdiff will only report the differences once per set of
hard links: if in a directory f1, f2 and
f3 are hard links while in the other f1 and
f2 are hard links while f3 exists but is not a
hard link, tdiff will report that f1 is only
linked to f3 in the first directory but will not
report the same information for f2 because f1
and f2 are part of the same set of hard linked files.
This is on by default.
−E, −−no−hardlinks
Will not report any differences in hard links sets.
−f, −−flags
Diff file system flags,
as found in the stat(2) st_flags structure
member. This is only supported on BSD, MacOSX and other
systems that have st_flags.
tdiff --version will list which file system flags
tdiff has been compiled with, but tdiff will
report even differences in other flags unknown at
compilation time, but will do so numerically instead of
listing the actual flag name.
This is on by default if your system’s stat(2)
structure has st_flags.
−F, −−no−flags
Do not diff file system flags.
−g, −−gid
Report on any differences in
file group ownership (owner group id, st_gid).
This is on by default.
−G, −−no−gid
Do not report any differences in file group ownership (owner group id).
−i, −−mtime
Report on any differences in file modification time (st_mtime), up to nanosecond resolution if the underlying OS reports it.
−I, −−no−mtime
Do not report any differences
in file modification times (st_mtime).
This is on by default.
−j, −−major
For device files (either block
or character), report any differences in major device
numbers.
Note that major numbers will only be compared if both device
files are of the same type (block or character).
This is on by default.
−J, −−no−major
Do not report any differences in major device numbers on device files.
−k, −−minor
For device files (either block
or character), report any differences in minor device
numbers.
Note that minor numbers will only be compared if both device
files are of the same type (block or character).
This is on by default.
−K, −−no−minor
Do not report any differences in minor device numbers on device files.
−l, −−acl
Report on any differences in
file ACLs as defined by acl_set_file(3).
Any missing or different ACLs between the file pairs are
reported. Access, default and mask ACL entries are
supported.
This is on by default if ACLs are supported by the
system.
−L, −−no−acl
Do not report any differences in file ACLs.
−m, −−mode
Report on any differences in
file access mode (permission bits as set by
chmod(1)). If set,
−o/−−mode−or and
−a/−−mode−and bitmasks
are applied, if set.
This is on by default.
−M, −−no−mode
Do not report any differences in file access modes (permission bits).
−n, −−nlink
Report on any differences in
file (hard) link counts (st_nlinks).
This is on by default.
−N, −−no−nlink
Do not report any differences in file (hard) link counts.
−q, −−xattr
Report on any differences in
file extended attributes as defined by setxattr(2).
Any missing or different extended attribute between the file
pairs is reported.
This is on by default if extended attributes are supported
by the system.
−Q, −−no−xattr
Do not report any differences in file extended attributes.
−s, −−size
Report file size
differences (st_size), except for directories which
are ignored.
This is on by default.
−S, −−no−size
Do not report file size differences.
−t, −−type
Report file type
differences (files, directories, symbolic links, etc.)
This is on by default.
−T, −−no−type
Do not report file type differences between the two compared directories.
−u, −−uid
Report on any differences in
file user ownership (owner user id, st_uid).
This is on by default.
−U, −−no−uid
Do not report any differences in file user ownership (owner user id).
−y, −−atime
Report on any differences in
file access time (st_atime), up to nanosecond
resolution if the underlying OS reports it.
Since merely reading a file causes the access time to be
updated, this option is likely to be of limited use.
tdiff will not update the file access times when
comparing files if compiled on an OS with O_NOATIME
open(2) support, whenever possible. One of the Operating
Systems with O_NOATIME support, Linux, only allows to
open a file with O_NOATIME if tdiff is ran by
the file owner or root. All files for which this is the case
will then be opened with NO_ATIME, but tdiff
will silently drop the O_NOATIME flag if a
Permission denied error is encountered. Please also
note that commands specified with
−x/−−exec,
−w/−−exec−always or
−W/−−exec−always−diff
may update the access times of the files they read.
−Y, −−no−atime
Do not report any differences
in file access times (st_atime).
This is on by default.
−z, −−ctime
Report on any differences in
file inode change time (st_ctime), up to nanosecond
resolution if the underlying OS reports it.
Since inode change times are automatically set by Unix to
the current time and cannot be changed afterwards, they will
always be reported as different for any two file trees,
except in rare cases (likely involving cloning raw file
system images).
−Z, −−no−ctime
Do not report any differences
in file file inode change times (st_ctime).
This is on by default.
The preset
single letter options are either a numeric preset level from
0 to 9, or −p followed by a
preset name or level. Presets can also be activated with the
−−preset long option followed by either a
numeric preset level or a preset name.
Preset names can be shortened to their smallest unambiguous
prefix. For example, −−preset
amtimes can be shortened to am, missing
to miss, default to d, etc.
The presets are cumulative, preset level 9 is a super-set of preset level 8, itself a super-set of level 7 and so on.
The default
preset level when tdiff starts parsing its options is
preset 6/notimes/default.
−0, −p|−−preset
0|none
Do not check anything. All the
toggles are set to their inactive
(−−no−) state.
If only this preset is active (it is provided last on the
command line for example), tdiff will not report
anything but will still traverse the file trees. This is
only useful to reset tdiff’s set of comparisons
to the empty set and add exactly which fields should be
compared with further toggle options.
−1, −p|−−preset 1|missing|type
Report missing files and
different file types.
tdiff will only emit messages for either files missing
in either directory
(−d/−−dirs) or if they are
of different file types
(−t/−−type). All the other
toggles are set to their inactive
(−−no−) state.
−2, −p|−−preset 2|mode
In addition to the comparisons enabled at preset level 1, tdiff will also enable file mode comparisons (−m/−−mode). All the other toggles are set to their inactive (−−no−) state.
−3, −p|−−preset 3|owner
In addition to the comparisons enabled at preset level 2, tdiff will also enable user id (−u/−−uid), group id (−g/−−gid) and, if supported, Access Control Lists (−l/−−acl) comparisons. All the other toggles are set to their inactive (−−no−) state.
−4, −p|−−preset 4|hardlinks
In addition to the comparisons enabled at preset level 3, tdiff will also enable link count (−n/−−nlink) and hard link targets (−e/−−hardlinks) comparisons. All the other toggles are set to their inactive (−−no−) state.
−5, −p|−−preset 5|contents
In addition to the comparisons enabled at preset level 4, tdiff will also compare file contents (−c/−−contents), size (−s/−−size), block usage (−b/−−blocks), and for device files, major (−j/−−major) and minor (−k/−−minor) device numbers. All the other toggles are set to their inactive (−−no−) state.
−6, −p|−−preset 6|notimes|default
In addition to the comparisons
enabled at preset level 5, tdiff will also
compare, if supported, flags
(−f/−−flags) and extended
attributes (−q/−−xattr). All
the other toggles are set to their inactive
(−−no−) state. This corresponds to
a state where all toggles are on except the three times
(−y/−−atime,
−i/−−mtime and
−z/−−ctime) that are off.
If your system does not support either flags or extended
attributes, then preset level 6 is equivalent to
preset level 5.
This is the default preset level.
−7, −p|−−preset 7|mtime
In addition to the comparisons enabled at preset level 6, tdiff will also compare file modification times (−i/−−mtime). This corresponds to a state where all toggles are on except the file access time (−y/−−atime) and the inode modification time (−z/−−ctime) that are off.
−8, −p|−−preset 8|amtimes
In addition to the comparisons enabled at preset level 7, tdiff will also compare file access times (−y/−−atime). This corresponds to a state where all toggles are on except the inode modification time (−z/−−ctime) that is off.
−9, −p|−−preset 9|alltimes|all
tdiff will compare all available attributes, turning all toggles on.
−a, −−mode−and MASK
When comparing file permission
bits, perform a binary and between the permission
bits and MASK before comparing them.
MASK is specified in octal, like with chmod(2),
unless prefixed with 0x, in which case it is parsed
as hexadecimal.
−o, −−mode−or MASK
When comparing file permission
bits, perform a binary or between the permission bits
and MASK before comparing them.
MASK is specified in octal, like with chmod(2),
unless prefixed with 0x, in which case it is parsed
as hexadecimal.
−w, −−exec−always COMMAND... \;
Always execute COMMAND
for any pair of matching regular files found in the trees.
Refer to the CONTENTS COMPARISONS section for
details.
If either options are specified more than once, the last
command defined will be used.
Using either option turns on the -c/--contents
toggle.
−W, −−exec−always−diff
Always execute diff −u for any pair of matching regular files found in the trees. This is a shortcut for:
tdiff −−exec−always diff −u %1 %2 \;
The option will supersede
whichever command was specified in a
−w/−−exec−always
option appearing earlier on the option list.
Using either option turns on the -c/--contents
toggle.
−x, −−exec COMMAND... \;
Uses COMMAND when
comparing files whose sizes are the same. Refer to the
CONTENTS COMPARISONS section for details.
If either options are specified more than once, the last
command defined will be used.
Using either option turns on the -c/--contents
toggle.
−X, −−exclude FILE
Excludes FILE from
processing: any discrepancies on a file or missing file
named FILE will not be reported. Neither will
external commands be ran on them. If FILE matches the
name of a directory, it will not be descended into and any
sub-directories or files it contains will be completely
ignored.
This option may be specified more than once, all the files
listed will be added to the exclusion list.
−O, −−follow−symlinks
Completely ignore symbolic
links and always fOllow and dereference them.
This is off by default (symbolic links are not followed /
dereferenced).
tdiff optimizes for hard links in two ways:
• |
tdiff will skip examining a pair of files if it has already compared the pair’s hard links copies. |
For example, if you have file1 hard linked to file2 in both DIRECTORY1 and DIRECTORY2, tdiff will only report any differences for file1 and will skip file2 entirely since it’s linked to file1 in both examined directories, and the list of differences would the same as for the already reported file1 case.
• |
tdiff will skip examining two hard-linked files. |
For example, if dir1/file is hard linked to dir2/file, then tdiff will omit examining the file pair entirely since they really are the same object and would have no differences at all.
tdiff’s hard link optimization depends on files’ inode and device numbers to be stable, unique and consistent at least for the duration of the tdiff run. This is generally the case for traditional file systems.
tdiff can optionally show which hard linked files are skipped and for what reason when run at the verbosity level 2 or above (-vv or --verbose --verbose).
tdiff uses built-in code for file contents comparisons. It avoid running an actual comparison if the file’s sizes (st_size) are different: the files with different sizes will be reported as having different contents without even comparing them as the size difference is enough to ascertain that their contents differ.
Optionally,
tdiff can run external commands to perform the
comparison. When providing an external command, the
COMMAND must be passed as multiple arguments
terminated by a semi-colon, which must be escaped to avoid
processing by the shell. COMMAND should not be quoted
as a single argument.
In the arguments can appear the strings %1 and
%2 which will be respectively replaced by the paths
to files in the first and second compared directories.
%1 and %2 can only appear once on the command
line, and must be full words: they cannot appear inside a
larger shell word.
For example:
tdiff --exec gtkdiff %1 %2 \; directory1 directory2
If either the −x or −−exec options are used, the command specified there will be ran instead of the built-in comparison and its exit status used to detect a difference (zero exit status meaning no difference, and non-zero meaning a difference). With either these options in effect, tdiff will not print any error message if the files are different, the command used for −x/−−exec should take care of reporting the error. Note that the command will not be ran if tdiff can find via the file size that the files differ by virtue of having different sizes.
If either the −w/−−exec−always or −W/−−exec−always−diff options are used, the command specified with these options will always be ran for every pair of regular files having the same path in both directories, whether or not they have the same size. The internal comparison pass will run and will report if the files are different, then the −w/−−exec−always/−W/−−exec−always−diff command will run. tdiff will record a difference if the −w/−−exec−always/−W/−−exec−always−diff command returns with non−zero exit status, even if the internal comparison or the −x/−−exec command are successful.
If both
−x/−−exec and
−w/−−exec−always/−W/−−exec−always−diff
options are used, then the command specified for
−x/−−exec will be ran if the
file sizes of the compared files are the same, and the
command specified by
−w/−−exec−always/−W/−−exec−always−diff
will always run.
This means that with options from both groups active, both
the −x/−−exec and
−w/−−exec−always/−W/−−exec−always−diff
commands will be ran for files with the same size.
tdiff exits with status:
0 |
if no discrepancies nor errors were encountered. | ||
1 |
if there were any problems with arguments or parsing the command line. | ||
2 |
if there were any differences reported, either by tdiff logging a discrepancy, or any of the −x/−−exec or −w/−−exec−always commands exiting with non-zero status. | ||
3 |
if there was any system error (a file couldn’t be read for example). | ||
4 |
if there was an internal error. This should not happen. |
Check that the two file trees rooted at directory1 and directory2 are exactly the same, including symbolic link targets if any, permissions, hard disk block usage, owner user and group ids, and if supported, flags, ACLs and extended attributes:
tdiff directory1 directory2
Same as previous example, but also check that the file modification times are the same:
tdiff -i directory1 directory2
Only report if any files are present in only one directory:
tdiff −0 −−dirs directory1 directory2
Report only ownership (user or group id) differences, ignore any missing files:
tdiff −0 −−uid −−gid directory1 directory2
Report only group permission bits differences, ignore any missing files:
tdiff −0 −−mode −−mode−and 70 directory1 directory2
or:
tdiff −0 −−mode −−mode−or 7707 directory1 directory2
Report only sticky bits differences, ignore any missing files:
tdiff −0 −−mode −−mode−and 1000 directory1 directory2
or:
tdiff −0 −−mode −−mode−or 6777 directory1 directory2
Run cmp −l on every file of the same size in both trees:
tdiff −0 −−exec cmp -l %1 %2 \; directory1 directory2
Run super-diff: diff files with diff −u and reports any other kind of differences in inode contents except for times:
tdiff −−exec−always−diff directory1 directory2
or more tersely:
tdiff −W directory1 directory2
Same with file modification times:
tdiff −W −−preset mtime directory1 directory2
or also:
tdiff −Wi directory1 directory2
Report bugs on the GitHub Issues page.
Copyright (C) 1999, 2008, 2014, 2019, 2024 Philippe Troin ( F-i-f on GitHub).
tdiff
comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute
it under certain conditions.
You should have received a copy of the GNU General Public
License along with this program. If not, see
http://www.gnu.org/licenses/.
acl_set_file(1), chmod(1), diff(1), getfacl(1), getfattr(1), open(2), setxattr(2), stat(2).