One of the things I love about Mac OS X is that, beneath the pretty and functional surface most people see, there’s a complete UNIX environment with all the tools a commandline jockey needs. And if something is missing, just install Xcode and homebrew and you’re good.
With this post I will kick off a series of short articles, published at highly irregular intervals, about the commandline utilities that come with Mac OS X and isn’t part of other UNIX-like operating systems.
Ditto can “… copy directory hierarchies, create and extract archives”, and it does so with a complete understanding of the peculiarities of Mac OS X filesystem resource forks, extended attributes, Access Control Lists and quarantine information.
All of these features are on by default since Mac OS X 10.5, as this is almost always what you want for backup purposes. There are quite self-explanatory
--noqtn options to shut those features off.
Copying a directory is straightforward:
% ls src a b c % ditto src dest % ls -F dest/ src/ % ls dest a b c
-V options to make
ditto more verbose about what it’s doing.
When creating an archive using the
-c option, files are per default stored as CPIO archives, or as ZIP archives with the
-k option. CPIO archives can optionally be compressed with either
-j options respectively.
A feature of
ditto is that it does not embed the parent directory in the archive by default, use
--keepParent for this. You also need to explicitly specify the output directory when extracting an archive. There’s a certain logic to this, given the directory copying capabilities of
ditto, but it’s counterintuitive compared to other common commandline archiving utilities. Let’s see an example, first without
% ls dir/ a b c % ditto -ck dir dir.zip # Create archive. % ls -F dir/ dir.zip % ditto -xk dir.zip output # Extract archive to ‘output’. % ls output a b c
This is not how
tar works for example. To get a more
tar-like behaviour, use
--keepParent when creating the archive:
% ditto --keepParent -ck dir dir.zip % ditto -xk dir.zip output % ls -F output dir/ % ls -F output/dir a b c
See? Nevermind that
tar defaults to the current directory as output directory and needs a
-C option to output to another directory.
If you are creating an archive to share with someone not on a Mac be sure to use the
--norsrc option to avoid creating
._* files on the target system. There’s no file exclusion option for ditto, so it is not directly possible to avoid archiving the
.DS_Store files. A workaround is the
--bom option, but then you need to create a BOM file, and that’s overkill in most situations, and—I think—another post entirely.