241

When I compress files with the built in zip compressor in Mac OSX, it causes an extra folder titled "__MACOSX" to be created in the extracted zip.

Can I adjust my settings to keep this folder from being created or do I need to purchase a third party compression tool?

UPDATE: I just found a freeware app for OSX that solves my problem: "YemuZip"

UPDATE 2: YemuZip is no longer freeware.

AJM
  • 1,317
  • 2
  • 15
  • 30
Scott B
  • 38,833
  • 65
  • 160
  • 266
  • The existence of _MACOSX folder doesn't creates any problem. Simply delete it. – Jayprakash Dubey Mar 14 '14 at 06:04
  • 3
    This question appears to be off-topic because it should be in AskDifferent – Nakilon Jan 12 '15 at 02:48
  • 23
    It creates a problem with picky web services that require a pristine zip archive, so I'm grateful for the explanations – mccc Nov 19 '15 at 18:15
  • 37
    @JayprakashDubey It's incredibily irritating, and as a linux user who likes not leaving trash everywhere I go, I can't stand `__MACOSX`, `.DS_Store`, `._fileName`, and all the other assorted turds Mac OS drops in its archives. OSX's `tar' does this as well - in blatant disregard for the [principle of least astonishment](https://en.wikipedia.org/wiki/Principle_of_least_astonishment). – Wyatt Ward Jun 28 '16 at 18:13
  • Also see: https://apple.stackexchange.com/questions/239578/compress-without-ds-store-and-macosx – GDP2 Aug 17 '21 at 23:32

16 Answers16

401

Can be fixed after the fact by zip -d filename.zip __MACOSX/\*

And, to also delete .DS_Store files: zip -d filename.zip \*/.DS_Store

Saikat
  • 14,222
  • 20
  • 104
  • 125
Chris Johnson
  • 20,650
  • 6
  • 81
  • 80
  • 63
    to also delete .DS_Store files: `zip -d filename.zip \*/.DS_Store` – Benedikt Köppel Jun 16 '15 at 14:28
  • 11
    The accepted answer says how not to get the __MACOSX/ directory in the first place, but says nothing about what to do with an existing .zip file. This answer says how to get rid of __MACOSX/ if you've already got it. However, the original question was how not to get it in the first place, so the accepted answer is the correct one. – Edward Falk Jun 22 '16 at 19:07
  • How might I do this recursively for all zip files? – Wowfunhappy Jun 27 '17 at 03:56
  • To apply to all zip files under some root: `find ~ -type f -name '*.zip' -exec zip -d '{}' __MACOSX/\* \;`. Substitute your starting point for `~`. – Chris Johnson Jun 27 '17 at 12:05
  • 1
    A function to remove all junk files: `cleanzip(){ zip -d $1 $2 __MACOSX/\* \*/.DS_Store; }`. Usage: `cleanzip file.zip` or `cleanzip file.zip MORE_JUNK_FILES` (second parameter is optional) – mrdaliri Aug 13 '17 at 13:45
  • @mrdaliri, note (1) it is unsafe to reference file path parameters without double-quoting them, and (2) there is no reason to limit to 2 parameters. Better to change your `$1 $2` to just `"$@"`. – Chris Johnson Aug 13 '17 at 13:49
  • Can someone elaborate on why `\*/` or `/\*` must be used? – cbrnr Oct 01 '18 at 11:23
  • You want the zip utility to interpret the wildcard, not the shell. The backslash escapes the asterisk so it isn't interpreted as a glob by the shell. You can use either `\*` or `'*'` (but not `"^"`) with the same effect. – Chris Johnson Oct 01 '18 at 11:27
  • Something is not OK with the `zip` command when used like https://apple.stackexchange.com/questions/239578/compress-without-ds-store-and-macosx If you unzip it later with PHP's `extractTo`, the extracted folder will not be named like the original zip. It will instead be named with the name given to the zip when `fopen`ed. However, if you zip the file with Mac finder, then that extracted folder will be of name as given to the Zip when zipped up. Thus, I prefer the command as suggested in this answer –  Dec 05 '22 at 08:33
126

When I had this problem I've done it from command line:

zip file.zip uncompressed

EDIT, after many downvotes: I was using this option for some time ago and I don't know where I learnt it, so I can't give you a better explanation. Chris Johnson's answer is correct, but I won't delete mine. As one comment says, it's more accurate to what OP is asking, as it compress without those files, instead of removing them from a compressed file. I find it easier to remember, too.

Koray Tugay
  • 22,894
  • 45
  • 188
  • 319
sinuhepop
  • 20,010
  • 17
  • 72
  • 107
  • 37
    This lacks explanation. – Raptor Aug 28 '14 at 11:35
  • 6
    The __MACOSX/ subdirectory contains Mac resource forks and is created when you use Mac tools to create the zip file. Likewise, Mac tools will consume the __MACOSX/ subdirectory in order to set resource forks, and you'll never even see it. However, if you use Mac tools to create the zip file and some other tools to unpack it, you'll get the __MACOSX/ directory and not the resource forks. If you create the file with `zip`, which is a 3rd-party app, then the __MACOSX/ directory never gets created in the first place. – Edward Falk Jun 22 '16 at 19:05
  • See my answer for an easy way to delete the _MACOSX folder after the zip file is created. – Chris Johnson Jun 23 '16 at 15:18
  • 7
    To compress a directory recursively without __MACOSX and other: `zip -rX file.zip uncompressed_directory` – Konstantin Suvorov Nov 25 '16 at 15:11
  • 2
    prevention is better than cure, and simple is better than complicated. Now if we add this a an Automator service we have ourselves a productivity beast here. Great solution. – Ogier Schelvis Jul 31 '20 at 10:08
93

Inside the folder you want to be compressed, in terminal:

zip -r -X Archive.zip *

Where -X means: Exclude those invisible Mac resource files such as “_MACOSX” or “._Filename” and .ds store files

source

Note: Will only work for the folder and subsequent folder tree you are in and has to have the * wildcard.

pompalini
  • 1,096
  • 7
  • 7
  • 11
    This does not work as you think it does: `-X` does not exclude .DS_Store files. The reason it may work for your application is that you're only zipping `*`, which is a wildcard matching files that don't begin with ".". Try it on a directory containing a dot-file, and you'll see it gets included. – SpinUp __ A Davis Sep 25 '14 at 15:34
  • See my answer for an easy way to delete the _MACOSX folder after the zip file is created. – Chris Johnson Jul 08 '15 at 12:32
  • 1
    No. Doing `zip -r -X Archive.zip myfolder` on a folder still results in a zip file containing .DS_Store file. – Rockallite Mar 11 '16 at 02:26
  • @Rockallite: you are correct this will only work when you zip the folders, tree or files in the folder you are in. Hence you cannot pass a folder as an argument or it won't work as expected, only with the * wildcard will it work. – pompalini Apr 14 '16 at 11:39
  • This works for files inside directories, instead of zipping a complete folder. – Michahell Apr 15 '16 at 09:10
  • 1
    Also see: https://apple.stackexchange.com/questions/239578/compress-without-ds-store-and-macosx – GDP2 Aug 17 '21 at 23:32
45

This command did it for me:

zip -r Target.zip Source -x "*.DS_Store"

Target.zip is the zip file to create. Source is the source file/folder to zip up. The -x parameter specifies the file/folder to exclude.

If the above doesn't work for whatever reason, try this instead:

zip -r Target.zip Source -x "*.DS_Store" -x "__MACOSX"
Adil Hussain
  • 30,049
  • 21
  • 112
  • 147
  • The OP asked how to exclude the __MACOSX folder. Your first code snippet obviously doesn't work, because it doesn't name that as a folder to exclude. – Chris Johnson Jul 08 '15 at 12:30
  • 9
    The `zip` command line utility never creates a `__MACOSX` directory, so the first snippet does work, and the `-x "__MACOSX"` part is not needed. – nisetama Jan 02 '16 at 18:56
20

I'm using this Automator Shell Script to fix it after. It's showing up as contextual menu item (right clicking on any file showing up in Finder).

while read -r p; do
  zip -d "$p" __MACOSX/\* || true
  zip -d "$p" \*/.DS_Store || true
done
  1. Create a new Service with Automator
  2. Select "Files and Folders" in "Finder"
  3. Add a "Shell Script Action"

automator shell script

contextual menu item in Finder

adamsfamily
  • 1,746
  • 19
  • 37
benedikt
  • 1,899
  • 2
  • 25
  • 30
  • Wouldn't it be better to do the compressing using zip in the Automator Shell Script, rather than compress using Apple built-in, then remove unwanted files? – Matt Mar 30 '17 at 03:45
  • @Matt you can add the archive step in automator or use another shell command as well. – ttimasdf Dec 19 '17 at 04:35
  • @Matt also, Apple built-in handles automatic file naming and name increment when file exists. With shell script this part would be a lot of work. – ttimasdf Dec 19 '17 at 04:54
  • 1
    It throws an error if the .DS_Store folder is not present in the archive. I suggest an improvement by adding ` || true` after each zip command (such as `zip -d "$p" __MACOSX/\* || true` into your answer. – adamsfamily Feb 26 '18 at 11:54
  • 2
    While the other answers are good, I like this one best because it can be used in a very Macish way. – not2savvy Apr 03 '18 at 10:44
14
zip -r "$destFileName.zip" "$srcFileName" -x "*/\__MACOSX" -x "*/\.*"
  • -x "*/\__MACOSX": ignore __MACOSX as you mention.
  • -x "*/\.*": ignore any hidden file, such as .DS_Store .
  • Quote the variable to avoid file if it's named with SPACE.

Also, you can build Automator Service to make it easily to use in Finder. Check link below to see detail if you need.

Github

Jian Jason
  • 141
  • 1
  • 5
12

The unwanted folders can be also be deleted by the following way:

zip -d filename.zip "__MACOSX*"

Works best for me

Machavity
  • 30,841
  • 27
  • 92
  • 100
SabU
  • 603
  • 6
  • 4
7

You can't.

But what you can do is delete those unwanted folders after zipping. Command line zip takes different arguments where one, the -d, is for deleting contents based on a regex. So you can use it like this:

zip -d filename.zip __MACOSX/\*
6

The zip command line utility never creates a __MACOSX directory, so you can just run a command like this:

zip directory.zip -x \*.DS_Store -r directory

In the output below, a.zip which I created with the zip command line utility does not contain a __MACOSX directory, but a 2.zip which I created from Finder does.

$ touch a
$ xattr -w somekey somevalue a
$ zip a.zip a
  adding: a (stored 0%)
$ unzip -l a.zip
Archive:  a.zip
  Length     Date   Time    Name
 --------    ----   ----    ----
        0  01-02-16 20:29   a
 --------                   -------
        0                   1 file
$ unzip -l a\ 2.zip # I created `a 2.zip` from Finder before this
Archive:  a 2.zip
  Length     Date   Time    Name
 --------    ----   ----    ----
        0  01-02-16 20:29   a
        0  01-02-16 20:31   __MACOSX/
      149  01-02-16 20:29   __MACOSX/._a
 --------                   -------
      149                   3 files

-x .DS_Store does not exclude .DS_Store files inside directories but -x \*.DS_Store does.

The top level file of a zip archive with multiple files should usually be a single directory, because if it is not, some unarchiving utilites (like unzip and 7z, but not Archive Utility, The Unarchiver, unar, or dtrx) do not create a containing directory for the files when the archive is extracted, which often makes the files difficult to find, and if multiple archives like that are extracted at the same time, it can be difficult to tell which files belong to which archive.

Archive Utility only creates a __MACOSX directory when you create an archive where at least one file contains metadata such as extended attributes, file flags, or a resource fork. The __MACOSX directory contains AppleDouble files whose filename starts with ._ that are used to store OS X-specific metadata. The zip command line utility discards metadata such as extended attributes, file flags, and resource forks, which also means that metadata such as tags is lost, and that aliases stop working, because the information in an alias file is stored in a resource fork.

Normally you can just discard the OS X-specific metadata, but to see what metadata files contain, you can use xattr -l. xattr also includes resource forks and file flags, because even though they are not actually stored as extended attributes, they can be accessed through the extended attributes interface. Both Archive Utility and the zip command line utility discard ACLs.

nisetama
  • 7,764
  • 1
  • 34
  • 21
  • This only works for directories, not for a bunch of file inside a directory. – Michahell Apr 15 '16 at 09:09
  • @MichaelTrouw Yes, but you should not usually create an archive that contains multiple files at the top level in the first place. – nisetama Apr 19 '16 at 00:37
  • 1
    I agree to disagree because there are use cases where this is fine. For example, one in which the end user of a zipfile will never be a user. But a server. – Michahell Apr 19 '16 at 10:28
4

Cleanup .zip from .DS_Store and __MACOSX, including subfolders:

zip -d archive.zip '__MACOSX/*' '*/__MACOSX/*' .DS_Store '*/.DS_Store'

Walkthrough:

  1. Create .zip as usual by right-clicking on the file (or folder) and selecting "Compress ..."
  2. Open Terminal app (search Terminal in Spotlight search)
  3. Type zip in the Terminal (but don't hit enter)
  4. Drag .zip to the Terminal so it converts to the path
  5. Copy paste -d '__MACOSX/*' '*/__MACOSX/*' .DS_Store '*/.DS_Store'
  6. Hit enter
  7. Use zipinfo archive.zip to list files inside, to check (optional)
Afanasii Kurakin
  • 3,330
  • 2
  • 24
  • 26
3

I have a better solution after read all of the existed answers. Everything could done by a workflow in a single right click. NO additional software, NO complicated command line stuffs and NO shell tricks.

The automator workflow:

  • Input: files or folders from any application.

  • Step 1: Create Archive, the system builtin with default parameters.

  • Step 2: Run Shell command, with input as parameters. Copy command below.

    zip -d "$@" "__MACOSX/*" || true

    zip -d "$@" "*/.DS_Store" || true

Save it and we are done! Just right click folder or bulk of files and choose workflow from services menu. Archive with no metadata will be created alongside.

IMAGE UPDATE: I chose "Quick Action" when creating a new workflow - here’s an English version of the screenshot:

enter image description here

Sample

Dave Everitt
  • 17,193
  • 6
  • 67
  • 97
ttimasdf
  • 1,367
  • 1
  • 12
  • 19
  • This is the best solution! Thank you so much! I used the camera in Google Translate to verify some of the specific settings in this screenshot (because I can't read Chinese myself, unfortunately), but this works beautifully. It creates a clean Archive.zip in the same folder. Very good. :-) – Erik van der Neut Aug 06 '20 at 01:40
  • @ErikvanderNeut sorry for the inconvenience, I just casually post a screenshot of my own configuration at that time I'll update the answer later – ttimasdf Aug 07 '20 at 03:08
  • It's all good man :-) I really like your solution, so thank you for posting it. – Erik van der Neut Aug 11 '20 at 12:32
  • 1
    It would be better if you capture the screenshot in English. – Anduin Xue Jun 22 '21 at 07:10
  • @Anduin - just added a screenshot in English after reproducing this for my own workflow. – Dave Everitt Sep 25 '22 at 11:47
2

do not zip any hidden file:

zip newzipname filename.any  -x "\.*"

with this question, it should be like:

zip newzipname filename.any  -x "\__MACOSX"

It must be said, though, zip command runs in terminal just compressing the file, it does not compress any others. So do this the result is the same:

zip newzipname filename.any
Xian Shu
  • 672
  • 6
  • 8
2

Keka does this. Just drag your directory over the app screen.

enter image description here

Christina
  • 34,296
  • 17
  • 83
  • 119
1

Do you mean the zip command-line tool or the Finder's Compress command?

For zip, you can try the --data-fork option. If that doesn't do it, you might try --no-extra, although that seems to ignore other file metadata that might be valuable, like uid/gid and file times.

For the Finder's Compress command, I don't believe there are any options to control its behavior. It's for the simple case.

The other tool, and maybe the one that the Finder actually uses under the hood, is ditto. With the -c -k options, it creates zip archives. With this tool, you can experiment with --norsrc, --noextattr, --noqtn, --noacl and/or simply leave off the --sequesterRsrc option (which, according to the man page, may be responsible for the __MACOSX subdirectory). Although, perhaps the absence of --sequesterRsrc simply means to use AppleDouble format, which would create ._ files all over the place instead of one __MACOSX directory.

Ken Thomases
  • 88,520
  • 7
  • 116
  • 154
  • 1
    Yes, I'm referring to the finder's "Compress" utility. As it is, I'm getting a folder full of ._ files which screws up WordPress' appearance/editor – Scott B Jun 07 '12 at 02:46
0

This is how i avoid the __MACOSX directory when compress files with tar command:

$ cd dir-you-want-to-archive $ find . | xargs xattr -l # <- list all files with special xattr attributes ... ./conf/clamav: com.apple.quarantine: 0083;5a9018b1;Safari;9DCAFF33-C7F5-4848-9A87-5E061E5E2D55 ./conf/global: com.apple.quarantine: 0083;5a9018b1;Safari;9DCAFF33-C7F5-4848-9A87-5E061E5E2D55 ./conf/web_server: com.apple.quarantine: 0083;5a9018b1;Safari;9DCAFF33-C7F5-4848-9A87-5E061E5E2D55

Delete the attribute first:

find . | xargs xattr -d com.apple.quarantine

Run find . | xargs xattr -l again, make sure no any file has the xattr attribute. then you're good to go:

tar cjvf file.tar.bz2 dir

0

Another shell script that could be used with the Automator tool (see also benedikt's answer on how to create the script) is:

while read -r f; do
    d="$(dirname "$f")"
    n="$(basename "$f")"
    cd "$d"
    zip "$n.zip" -x \*.DS_Store -r "$n"
done

The difference here is that this code directly compresses selected folders without macOS specific files (and not first compressing and afterwards deleting).

Jurij
  • 11