TDIFF(1)
π¦ TDIFF(1) β User Commands π¦
okay bestie, welcome to the tdiff(1) page β it's giving tree diff, and yes we're keeping every single flag. π
β¨ NAME β¨
tdiff β tree diff, list differences between various inode attributes (stat(2) structure) and contents for two directory trees.
π¦ SYNOPSIS π¦
tdiff [OPTIONS]... DIRECTORY1 DIRECTORY2
π DESCRIPTION π
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.
π OPTIONS π
β Standard 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 thetdiffversion information, compiled-in features and flags (if any) then exit. The compiled-in feature list shows which featurestdiffhas been compiled with:O_NOATIME, flags, acl, and xattr support, thereaddir(2)implementation used, and the file system time granularity (either seconds (s) or nanoseconds (ns)). If flags support is compiled in, the list of recognized flags will be listed as well.
π Toggle Options π
The single-letter toggle options come in two versions, upper-case and lower-case. The lower-case option enables 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,tdiffwill report that the files are hard links only in the first directory.tdiffwill only report the differences once per set of hard links: if in a directoryf1,f2andf3are hard links while in the otherf1andf2are hard links whilef3exists but is not a hard link,tdiffwill report thatf1is only linked tof3in the first directory but will not report the same information forf2becausef1andf2are 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 thestat(2)st_flagsstructure member. This is only supported on BSD, MacOSX and other systems that havest_flags.tdiff --versionwill list which file system flagstdiffhas been compiled with, buttdiffwill 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'sstat(2)structure hasst_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 byacl_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 bychmod(1)). If set,-o/--mode-orand-a/--mode-andbitmasks 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 bysetxattr(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.tdiffwill not update the file access times when comparing files if compiled on an OS withO_NOATIMEopen(2)support, whenever possible. One of the Operating Systems withO_NOATIMEsupport, Linux, only allows to open a file withO_NOATIMEiftdiffis ran by the file owner or root. All files for which this is the case will then be opened withNO_ATIME, buttdiffwill silently drop theO_NOATIMEflag if a Permission denied error is encountered. Please also note that commands specified with-x/--exec,-w/--exec-alwaysor-W/--exec-always-diffmay 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 inode change times (st_ctime). This is on by default.
π Preset Options π
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.
okay so the presets are cumulative β preset level 9 is a whole super-set of preset 8, which is itself a super-set of 7, and so on down the line. Each one just keeps stacking more comparisons on top π
And the default preset level when tdiff first starts parsing its options is preset 6/notimes/default β¨
-0,-p|--preset0|noneβ check literally nothing, bestie. Every toggle gets flipped to its inactive (--no-) state. If this preset is the only one active (like, it's the last thing you passed on the command line),tdiffwon't report a single thing but it will still walk the file trees. This is only useful for resettingtdiff's comparison set back to empty and then adding exactly the fields you actually want with more toggle options π-1,-p|--preset1|missing|typeβ reports missing files and files whose types differ.tdiffwill only emit messages for files missing in either directory (-d|--dirs) or for files that are different file types (-t|--type). All the other toggles go to their inactive (--no-) state.-2,-p|--preset2|modeβ on top of everything preset level 1 does,tdiffalso turns on file mode comparisons (-m|--mode). All the other toggles: inactive (--no-).-3,-p|--preset3|ownerβ adds to level 2, so now you also get user id (-u|--uid), group id (-g|--gid) and, if your system supports it, Access Control Lists (-l|--acl) comparisons. Everything else is inactive (--no-).-4,-p|--preset4|hardlinksβ adds to level 3: link count (-n|--nlink) and hard link targets (-e|--hardlinks) comparisons. All the other toggles stay inactive (--no-).-5,-p|--preset5|contentsβ adds to level 4, so now it compares file contents (-c|--contents), size (-s|--size), block usage (-b|--blocks), and for device files, the major (-j|--major) and minor (-k|--minor) device numbers. All the other toggles: inactive (--no-).-6,-p|--preset6|notimes|defaultβ adds to level 5: flags (-f|--flags) and extended attributes (-q|--xattr), if supported. All the other toggles are inactive (--no-). This is the state where every toggle is on except the three times (-y|--atime,-i|--mtimeand-z|--ctime), which are off. If your system doesn't support flags or extended attributes, preset level 6 is literally equivalent to preset level 5. This is the default preset level π-7,-p|--preset7|mtimeβ adds to level 6, sotdiffalso compares file modification times (-i|--mtime). That's all toggles on except file access time (-y|--atime) and inode modification time (-z|--ctime), which are off.-8,-p|--preset8|amtimesβ adds to level 7: file access times (-y|--atime). All toggles on except inode modification time (-z|--ctime), which is off.-9,-p|--preset9|alltimes|allβtdiffcompares all available attributes, every toggle on. Go off, queen π₯
π¦ Other Miscellaneous Options π¦
-a,--mode-andMASK β when comparing file permission bits, does a binary and between the permission bits and MASK before comparing. MASK is in octal, just like withchmod(2), unless you prefix it with0x, in which case it's parsed as hexadecimal π§-o,--mode-orMASK β same deal but a binary or between the permission bits and MASK before comparing. MASK is octal, like withchmod(2), unless prefixed with0xfor hexadecimal β¨-w,--exec-alwaysCOMMAND...\;β always runs COMMAND for any pair of matching regular files it finds in the trees. Details live in the CONTENTS COMPARISONS section, iykyk. If either of these options shows up more than once, the last command defined is the one that gets used. Using either option turns on the-c|--contentstoggle.-W,--exec-always-diffβ always runsdiff -ufor any pair of matching regular files in the trees. It's a shortcut for:
tdiff --exec-always diff -u %1 %2 \;
This option supersedes whatever command was given in a -w|--exec-always option appearing earlier in the option list. Using either option turns on the -c|--contents toggle π
-x,--execCOMMAND...\;β uses COMMAND when comparing files whose sizes are the same. Again, the CONTENTS COMPARISONS section has the full tea. If either of these options is specified more than once, the last command defined wins. Using either option turns on the-c|--contentstoggle.-X,--excludeFILE β excludes FILE from processing: any discrepancies on a file, or a missing file, named FILE won't be reported. External commands won't be run on them either. If FILE matches the name of a directory,tdiffwon't descend into it and every sub-directory and file inside is completely ignored π This option can be specified more than once β all the files you list get added to the exclusion list.-O,--follow-symlinksβ completely ignores symbolic links and always fOllows and dereferences them. This is off by default (so by default symlinks are not followed / dereferenced) β
π HARD LINKS π
tdiff optimizes for hard links in two ways, and honestly? iconic behaviour:
tdiffskips examining a pair of files if it's already compared that pair's hard link 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 be the same as the already-reported file1 case π«Ά
tdiffskips examining two hard-linked files.
For example, if dir1/file is hard linked to dir2/file, then tdiff omits examining that file pair entirely, because they really are the same object and would have no differences at all. No cap π
tdiff's hard link optimization depends on the files' inode and device numbers being stable, unique and consistent at least for the duration of the tdiff run. That's generally true for traditional file systems πΈ
tdiff can optionally show which hard linked files are skipped and why, when you run it at verbosity level 2 or above (-vv or --verbose --verbose) π
π CONTENTS COMPARISONS π
tdiff uses built-in code for file contents comparisons. It avoids running an actual comparison if the files' sizes (st_size) differ: files with different sizes get reported as having different contents without even comparing them, because the size difference alone is enough to ascertain that their contents differ. Efficient queen π
Optionally, tdiff can run external commands to do the comparison. When you provide an external command, the COMMAND must be passed as multiple arguments terminated by a semi-colon, which must be escaped so the shell doesn't eat it. COMMAND should not be quoted as a single argument. In the arguments you can put the strings %1 and %2, which get replaced with the paths to the files in the first and second compared directories respectively. %1 and %2 can only appear once on the command line and must be full words: they can't be tucked 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 runs instead of the built-in comparison, and its exit status is what detects a difference (zero exit status = no difference, non-zero = difference). With either of these options in effect, tdiff will not print any error message if the files are different β the command used for -x|--exec is supposed to handle reporting the error itself. Note that the command will not be run if tdiff can tell 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 always runs 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 runs and reports if the files are different, and then the -w|--exec-always / -W|--exec-always-diff command runs. tdiff records a difference if the -w|--exec-always / -W|--exec-always-diff command returns a non-zero exit status β even if the internal comparison or the -x|--exec command succeeded π
If both -x|--exec and -w|--exec-always / -W|--exec-always-diff options are used, then the command specified for -x|--exec runs when the compared files have the same size, and the command specified by -w|--exec-always / -W|--exec-always-diff always runs. Which means: with options from both groups active, both the -x|--exec and the -w|--exec-always / -W|--exec-always-diff commands run for files with the same size π¦
πͺ EXIT STATUS πͺ
tdiff exits with status:
0β if no discrepancies nor errors were encountered. The dream π1β if there were any problems with arguments or parsing the command line.2β if there were any differences reported, either bytdifflogging a discrepancy, or any of the-x|--execor-w|--exec-alwayscommands 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. π
πΈ EXAMPLES πΈ
Okay bestie, this is the fun part β real tea, real commands. Every one of these is copy-paste-able, so go off π
π Example one β the full vibe check. Want to check that the two file trees rooted at directory1 and directory2 are exactly the same? That means: symbolic link targets if any, permissions, hard disk block usage, owner user and group ids, and β if supported β flags, ACLs and extended attributes. All of it. No cap.
tdiff directory1 directory2
β¨ Same as the previous one, but spicy. This is the exact same check, but it also verifies that the file modification times match. Clocks out, calendars out π°οΈ
tdiff -i directory1 directory2
π¦ Just the missing-files gossip. Only report if any files are present in only one directory. Nothing else. Minimalist queen behavior.
tdiff -0 --dirs directory1 directory2
π Ownership only, bestie. Report only ownership (user or group id) differences, and ignore any missing files. We don't care about the missing ones, we care about who owns what π
tdiff -0 --uid --gid directory1 directory2
π Group permission bits only. Report only group permission bits differences, ignore any missing files. Two ways to do it, pick your fighter:
tdiff -0 --mode --mode-and 70 directory1 directory2
or:
tdiff -0 --mode --mode-or 7707 directory1 directory2
π₯ Sticky bits only. Report only sticky bits differences, ignore any missing files. Again, two flavors β or, well, -and and -or, lol:
tdiff -0 --mode --mode-and 1000 directory1 directory2
or:
tdiff -0 --mode --mode-or 6777 directory1 directory2
π§ The byte-by-byte detective era. Run cmp -l on every file of the same size in both trees. Every. Single. One. Obsessed with the thoroughness honestly.
tdiff -0 --exec cmp -l %1 %2 \; directory1 directory2
π Super-diff time β main character energy. This runs the super-diff: it diffs files with diff -u and reports any other kind of differences in inode contents except for times. So basically everything except mtime gets caught.
tdiff --exec-always-diff directory1 directory2
or, more tersely (because we love efficiency):
tdiff -W directory1 directory2
β Super-diff, but now with timestamps. Same deal as above, except now file modification times are in the mix too:
tdiff -W --preset mtime directory1 directory2
or also:
tdiff -Wi directory1 directory2
π«Ά REPORTING BUGS
Found something cursed? Report bugs on the GitHub Issues page. Do it, bestie β that's how the software gets better π
π COPYRIGHT
Copyright (C) 1999, 2008, 2014, 2019 Philippe Troin ( F-i-f on GitHub).
tdiff comes with ABSOLUTELY NO WARRANTY. Like, none. Zero. Don't come for them if it breaks. 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/.
π SEE ALSO
Go read these too, iykyk:
acl_set_file(1)chmod(1)diff(1)getfacl(1)getfattr(1)open(2)setxattr(2)stat(2)
And that's the whole page, bestie π This is tdiff version 0.8.4, dated June 2019 β go forth, compare your trees, and slay πβ¨πΈ
π¦ where this page comes from
- opensuse-leap 16.0: tdiff 0.8.6-bp160.1.12 Β· GPL-3.0-or-later
- opensuse-leap 16.0: tdiff 0.8.6-bp160.1.12 Β· GPL-3.0-or-later
- opensuse-leap 16.0: tdiff 0.8.6-bp160.1.12 Β· GPL-3.0-or-later
- opensuse-leap 16.0: tdiff 0.8.6-bp160.1.12 Β· GPL-3.0-or-later
- Copyright (C) 2019 Philippe Troin <phil+github-commits@fifi.org>
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms