Compare folders on Mac OS X: what each tool can see
Run two different folder comparisons over the same pair of directories and they will often disagree. One reports the folders as identical, another lists forty differences, a third finds files that appear to exist in only one side even though both show the same item on screen. None of the tools is broken. They are answering different questions, and macOS is adding files and metadata that some of them count and others ignore. The useful skill is not picking a favourite tool. It is knowing what each one looks at, and what the operating system puts in a folder that was never part of the work.
What is already installed
Nothing needs to be bought to compare two directories on a Mac. Six things are on the machine already, and each one is blind to something.
| Tool | What it reports | What it does not see |
|---|---|---|
diff -rq A B |
Which files differ, which exist on one side only | Permissions, extended attributes, empty directory differences in some cases |
cmp -s a b |
Whether two individual files are byte identical | Anything about the directory structure |
rsync -avn A/ B/ |
What a sync would transfer, using size and modification time | Content changes that preserve both size and timestamp |
rsync -avnc A/ B/ |
The same, using full file checksums | Metadata that rsync is not asked to carry |
shasum over a file list |
A record that can be compared again later | Names that exist on one side only, unless the lists are diffed |
opendiff |
A visual, side by side view of two trees | Requires Xcode to be installed |
Two entries deserve a note. opendiff is a small shim in /usr/bin that launches FileMerge, which lives inside Xcode at Contents/Applications/FileMerge.app. Without Xcode the command exists but has nothing to open.
The other is rsync. On current macOS the binary at /usr/bin/rsync is openrsync, and man rsync opens a page headed OPENRSYNC. It reports itself as compatible with rsync 2.6.9. That matters when following older guides, because options assumed to exist may behave differently or not be present at all. Checking man rsync on the actual machine is faster than debugging a flag that was written for a different implementation.
The diff on macOS is worth the same check. It identifies itself as Apple diff based on FreeBSD diff, not the GNU version that most online examples assume. The common flags behave the same way, and -r, -q, -x and -X are all present, but anything more exotic taken from a GNU manual should be confirmed locally rather than assumed. The output vocabulary is fixed and easy to script against: a line reading Files A/x and B/x differ for a content difference, and Only in A: x for something present on one side. Binary files produce the same differ line rather than a dump, so a mixed tree of documents and images can be compared without special handling.
There is also the question of what a comparison does with links and empty folders, which is where tools quietly diverge. A symbolic link can be treated as a small file containing a path, or followed to whatever it points at, and the two produce completely different reports when a tree contains links to material outside it. Empty directories are similar: some tools list them as a difference, others only care about files, so a folder that exists on one side with nothing in it may or may not appear. Neither behaviour is wrong, and both are worth confirming on a small test pair before running anything against real material.
The files macOS puts in a folder that are not yours
Every folder that has been opened in Finder tends to acquire a .DS_Store file holding that folder's view settings: icon positions, sort order, window size. It is invisible in Finder and very visible to any tool that walks the directory. Two folders with identical work in them will differ in .DS_Store almost immediately after both are browsed, which is enough to make a naive comparison report a difference on nearly every directory.
Apple documents the file in the context of network shares, where reading them slows browsing down:
To speed up SMB file browsing, you can prevent macOS from reading .DS_Store files on SMB shares. This makes the Finder use only basic information to immediately display each folder's contents in alphanumeric order. Source: support.apple.com
There are more of these. On volumes that cannot store Mac metadata natively, such as exFAT sticks and many network shares, extended attributes are written into companion files whose names start with ._ followed by the original name. Removable volumes also collect .Spotlight-V100, .fseventsd and .Trashes at the root. None of it is part of the material being compared, and all of it will be reported as a difference unless excluded.
The exclusions are worth keeping somewhere reusable. diff takes -x for a single pattern and -X file for a list of patterns read from a file, so a small exclusions file used for every comparison saves rewriting the same flags. rsync uses --exclude for the same job. Setting this up once removes the majority of the false differences that make people distrust the results.
Two names that look the same, and one pair that cannot coexist
The second source of disagreement is that a name on screen and a name on disk are not the same thing.
Japanese and other scripts that use combining marks can be written in two forms. The character can be stored as one code point, or as a base character followed by a separate mark. Both display identically. APFS treats the two forms as the same name: creating a file with the composed form and then creating one with the decomposed form leaves a single file in the folder, not two. The forms come from real places. Archives built on other systems, older data from the HFS Plus era, and some downloads all carry the decomposed form.
For comparison this cuts two ways. A tool that compares raw directory listings byte for byte will report two names as different when the filesystem considers them the same. A tool that asks the filesystem will report them as one. Both answers are defensible, which is why the same folder pair can produce different results in different applications.
Case does something similar with a harsher outcome. The default macOS volume does not distinguish Notes.txt from notes.txt, so a folder that contains both, having been built on a case-sensitive volume or unpacked from an archive, cannot be reproduced faithfully on a normal Mac. The comparison will report the pair as one file, and the copy that produced it lost data before the comparison was ever run.
Metadata that no directory comparison reports
diff compares contents. Two files that it calls identical can still behave differently on the machine, because a file on macOS carries information stored outside its data.
Extended attributes are where Finder tags and comments live, alongside the quarantine flag that macOS sets on downloads. ls -l@ shows which files carry them and xattr -l prints them. A copy made with cp or ditto keeps them. A round trip through the command line zip and unzip does not, so a folder restored from an archive can be byte identical in every file and have lost every tag.
Permissions and ownership are in the same category. A folder synchronised without preserving them can be identical in content and unusable for the purpose it was copied for. Access control lists, visible with ls -le, are one more layer that most comparisons ignore entirely.
The practical consequence is a habit rather than a tool. Decide before running anything whether the question is about content only or about the file as the system sees it. If it is the latter, the comparison has to be told to look, and the tool that gives the plainest answer is xattr -l run over the two candidates rather than any directory level report.
When a paid tool earns its place
The commands above answer questions. They do not help much when the task is to look at two large trees and decide what to do with three hundred differences. That is the work graphical tools are built for, and it is where a dual pane file manager with a synchronise view fits. ForkLift's own description of the feature is a fair summary of the category:
source and target folders identifying matching, modified, new and deleted files. Source: binarynights.com
Prices in this category are one time rather than subscription in several cases. ForkLift 4 is 19.95 US dollars. Commander One PRO is 29.99 US dollars. Transmit 5 is 45 US dollars and is a transfer application rather than a comparison one, which matters when the folders being compared are on a server. Cyberduck is free from the developer's own site and is also listed as a paid item in the Mac App Store, which is a common arrangement and not a different product.
One macOS change is worth knowing before planning any remote comparison. There is no longer an ftp command in macOS, so comparing a local folder against a plain FTP server means mounting it or using an application that speaks the protocol. Anything written before that removal will suggest a command that is not there.
Choosing by the question rather than the tool
Reduced to a decision, most comparisons fall into one of three cases. If the question is whether a copy completed correctly, the answer needs full file checksums, and speed is not the priority. If the question is which side has newer work, timestamps are the right signal and a checksum pass is wasted effort. If the question is what changed inside a set of documents, a visual tool that can show the differences inside each file is worth the switch from the terminal.
There is a fourth case that is really a workflow problem. Comparing folders once is a task. Comparing them repeatedly, while also opening the differences, running commands against them, and moving items between the two sides, is a loop across several applications. A comparison of how different file managers lay this out is more informative than a feature checklist, because the difference between them is where the panes are rather than which formats they read. The capability list is worth reading with that in mind.
What to change first
Build the exclusions file before anything else, put .DS_Store and ._* in it, and use it in every comparison from now on, because most of the noise disappears at that point. Then decide, per job, whether the honest answer needs checksums or timestamps. If the comparison is a step inside a longer loop of inspecting and fixing, the tool that removes the switching is a single window holding the folders, the terminal and the assistant, which is what Atriens is.
Frequently asked questions
Why does every folder comparison report differences in files I never created?
Almost always .DS_Store, which Finder writes into any folder it displays to remember icon positions and sort order. On removable and network volumes, files beginning with ._ and directories such as .Spotlight-V100 appear for the same reason. Exclude them with diff -x or an exclusions file and the real differences become visible.
Is the rsync on macOS the same as the rsync in older tutorials?
No. On current macOS the command at /usr/bin/rsync is openrsync, and its manual page is headed OPENRSYNC. It reports compatibility with rsync 2.6.9, so options introduced later may behave differently or be absent. Check man rsync on the machine before copying flags from an old guide.
Do I need Xcode to use FileMerge?
Yes. The opendiff command in /usr/bin is a shim that launches FileMerge, and FileMerge itself is inside the Xcode application bundle. Without Xcode installed the command is present but has nothing to open, which is why it appears to fail silently.
Two filenames look identical on screen but the tools disagree. What is happening?
The characters are almost certainly stored in two different Unicode forms, one composed and one decomposed. Both display the same. APFS treats them as the same name, so it will not hold both, while a tool comparing raw text sees two different strings. Files carrying the decomposed form usually arrive from archives or from older data.