Zipping on a Mac for someone opening it on Windows
The file went out as a single archive. The reply comes back with a screenshot: half the names are unreadable symbols, there is a folder called __MACOSX sitting next to the real one, and every document has a twin whose name starts with ._. Nothing was corrupted in transit. The archive is exactly what the Mac wrote, and the Windows machine is reading it exactly as the format tells it to.
This is worth separating from a transfer failure, because the fixes are different. A damaged upload is solved by sending it again. This one is solved by building the archive differently, and part of it cannot be solved with the tools that ship with macOS at all.
The four things that arrive wrong, and what each one is
Complaints about a Mac made zip on Windows almost always fall into four buckets, and they have nothing to do with each other.
Names come out as unreadable characters. This is a character encoding question, decided by a single bit in each archive entry.
An extra __MACOSX folder appears alongside the real contents, full of files prefixed with ._. These are AppleDouble files. They carry resource forks and extended attributes that the zip format has no field for, so the archiver parks them in a shadow directory.
A hidden .DS_Store file shows up in every folder. That is the per folder view state the Finder writes: icon positions, window size, sort order. It is meaningless on Windows and gets included because it is a normal file on disk.
Extraction stops partway with a path error. That is either a character that is legal in a macOS name and illegal in a Windows one, or a path that grew past the length the extractor allows.
Fixing all four takes about a minute once the cause of each is clear. Guessing at them takes several rounds of resending.
Why the names break, and why the Mac cannot flag them correctly
The zip format stores a filename as raw bytes plus a flag that says how to read those bytes. The specification is explicit about which flag:
Bit 11: Language encoding flag (EFS). If this bit is set, the filename and comment fields for this file MUST be encoded using UTF-8. Source: pkware.cachefly.net
When that bit is clear, an extractor is entitled to assume the legacy behaviour, which on a Japanese Windows install means decoding the bytes with the system code page rather than as UTF-8. The bytes are perfectly good UTF-8. The reader was told to treat them as something else.
Inspecting archives built on a current macOS shows the flag is not set. Both a folder compressed with the bundled zip command and one archived with ditto -c -k store their entries as UTF-8 bytes with bit 11 clear. Decoding those bytes as UTF-8 gives back the original Japanese names; decoding them with a legacy Japanese code page fails outright.
The reason is visible in the tool itself. Running zip -v on macOS prints the build banner for Info-ZIP Zip 3.0, and the line reading Zip special compilation options comes back empty. Unicode support is one of those compile time options, so the flag setting switches documented in the help text are not actually present in the shipped binary. Passing -UN=UTF8 returns an argument error rather than a flagged archive.
That is the honest limit. With only the tools that come with macOS, there is no supported way to produce an archive whose entries announce themselves as UTF-8. The workarounds are to avoid non-ASCII characters in the names being sent, or to build the archive with a third party archiver that sets the flag.
Where __MACOSX comes from
The shadow folder is not a bug and not a leftover. It is a documented feature of the copying tool macOS uses for archives. The manual page for ditto describes its --sequesterRsrc option like this:
When creating a PKZip archive, preserve resource forks and HFS meta-data in the subdirectory __MACOSX. PKZip extraction will automatically find these resources. Source: keith.github.io
Extracting on another Mac hides those entries again and reattaches the metadata, which is why the problem is invisible until the archive reaches a machine that does not know the convention. On Windows they are ordinary files and get listed as ordinary files.
The ._ files exist for the same reason even outside archives. Copying to a volume that cannot store extended attributes, such as a FAT formatted USB stick, leaves the same pairs behind. macOS ships dot_clean for exactly this cleanup, and its usage line lists -m as always delete apple double files. Running it over a folder before archiving removes the pairs that would otherwise be swept into the zip.
Building an archive that arrives clean
The differences between the available methods are worth knowing before picking one.
| Method | AppleDouble entries | .DS_Store |
UTF-8 flag on names |
|---|---|---|---|
| Compress in the Finder | Written into __MACOSX |
Included | Not set |
zip -r archive.zip folder |
None | Included unless excluded | Not set |
ditto -c -k --sequesterRsrc |
Written into __MACOSX |
Included | Not set |
ditto -c -k --norsrc --noextattr |
None | Included | Not set |
| Third party archiver | Depends on the tool | Depends on the tool | Usually set |
Two of those rows are worth reading twice. The bundled zip command does not create AppleDouble entries at all, which makes it a better starting point than the Finder for anything leaving the platform. And no row that relies only on preinstalled software sets the encoding flag, which is why the naming rule below is not optional.
A workable recipe for a Windows recipient looks like this. Strip the shadow files first, then archive with exclusions:
dot_clean -m ~/Desktop/handover
cd ~/Desktop
zip -r -X handover.zip handover -x "*.DS_Store" -x "__MACOSX/*"
The -X switch drops most of the extra fields that only mean something on the originating system. The exclusion patterns have to come after the input path, not before it, or the command exits with a selection error.
Names that are legal here and illegal there
macOS and Windows disagree about what a filename may contain, and the disagreement only surfaces at extraction time.
Windows reserves \ / : * ? " < > | in filenames. A colon is the one that catches people out, because a colon typed in the Finder is not stored as a colon at all, and a name written from the command line can contain one without complaint. Windows also refuses names matching legacy device names such as CON, PRN, AUX and NUL, with or without an extension, and drops trailing dots and spaces.
Length is the other trap. A single filename component on macOS can hold 255 bytes, and that is bytes rather than characters, so Japanese names hit the ceiling roughly three times sooner than Latin ones. On the Windows side the constraint applies to the whole path, and many extractors still refuse to write a path longer than 260 characters. A deeply nested folder that works locally can fail once the recipient extracts it three levels down inside a user profile.
Case sensitivity is the quiet one. A macOS volume is normally case insensitive but case preserving, so Report.pdf and report.pdf cannot sit in the same folder locally and the conflict never comes up. Archives built on a case sensitive volume, or assembled from several sources by a script, can carry both. Extracting that on Windows silently overwrites one with the other, and the recipient ends up with a file count that does not match the listing.
The practical rule: flatten the structure before archiving, and keep the sent names to ASCII letters, digits, hyphens and underscores. That single rule removes the encoding problem and the illegal character problem together.
What the recipient's extractor decides
The same archive behaves differently depending on what opens it, which is why one colleague reports garbled names and another does not.
The extraction built into Windows Explorer takes no options. It reads the archive, applies its own decoding rule for unflagged entries, and writes the result. There is no place to choose an encoding, no place to skip entries, and no way to tell it that the folder full of ._ files is metadata rather than content.
Standalone archivers behave differently. Several of them let the user nominate a character encoding at extraction time, which turns an unflagged UTF-8 archive back into readable names in one step, and several offer a path length mode that gets around the classic limit. Asking a recipient to install one is a legitimate answer for an ongoing exchange with the same person. It is a poor answer for an archive going to a customer, a public download, or anyone who will not read the instructions.
Because the sender cannot know which of these will be used, the archive has to be readable under the least capable of them. Building for the built in extractor and letting the better tools handle it easily is the order that works. Building for a specific third party tool and hoping the recipient has it is the order that produces the screenshot at the top of this page.
Checking the archive before it leaves
Guessing whether an archive is clean is unnecessary. Listing it shows the answer:
unzip -l handover.zip
If __MACOSX, ._ or .DS_Store appear in that listing, they will appear on the recipient's screen too. If the Japanese names in the listing print as broken characters in the terminal, that is the same missing flag the recipient will hit, shown by a different tool.
Checking the flag directly takes one line:
python3 -c "import zipfile,sys;[print(bool(i.flag_bits&0x800), i.orig_filename) for i in zipfile.ZipFile(sys.argv[1]).infolist()]" handover.zip
True in the first column means the entry announces itself as UTF-8 and any modern extractor will read it correctly. False means the recipient's tool is guessing.
One more check is worth the ten seconds it takes. Compare the number of entries in the listing against the number of files that were meant to go in. An archive that reports twice as many entries as expected is carrying an AppleDouble twin for every file, and the recipient will see both sets. An archive that reports fewer is missing something that an exclusion pattern caught by accident, which happens when a wildcard is broader than intended.
None of this needs to become a ritual. It becomes worth automating the moment the same handover repeats, at which point the three commands belong in a saved script rather than in memory.
This is the kind of check that is easy to describe and easy to skip, because running it means leaving the folder view, finding a terminal, and typing the path again. Keeping the folder and the command line in one window removes that friction, which is the whole design premise behind a file manager with a terminal in the same window. How that compares with a two pane manager or a transfer client is laid out on the comparison page, and what it costs is on the pricing page.
What to change first
Rename anything non-ASCII before archiving, then build the archive with zip -r -X and the two exclusions rather than the Finder's compress command. Those two steps remove the reported symptoms without asking the recipient to install anything. If archives for Windows are a weekly job rather than a one off, run that pair of commands from the same window as the folder, which is what Atriens exists to do.
Frequently asked questions
Why do the names look fine on another Mac and broken on Windows?
Both machines read the same bytes, but only one of them guesses UTF-8 by default. macOS treats unflagged entries as UTF-8, so the archive looks correct. A Windows extractor falls back to the system code page unless bit 11 is set, and that bit is not set by the tools included with macOS.
Is it safe to delete the `__MACOSX` folder after extracting?
On Windows the contents are inert. They hold resource forks and extended attributes that Windows has no use for, so deleting the folder and the ._ files removes nothing the recipient can read. Deleting them from an archive that will be extracted on a Mac loses metadata such as tags and custom icons.
Does compressing in the Finder differ from the `zip` command?
Yes, in one visible way. The Finder route goes through the archiving tool that sequesters resource forks into __MACOSX, while the bundled zip command does not create those entries at all. Neither route sets the UTF-8 flag on filenames, so that part is identical.
Can the recipient fix the garbled names on their side?
Sometimes. An archiver that lets the user pick a character encoding at extraction time can read the entries as UTF-8 manually. The built in Windows extractor gives no such choice, so if the recipient is using that, the archive has to be rebuilt with ASCII names or with a tool that sets the flag.