Is it possible to clone directories in APFS?

APFS supposedly

features cloning for files and directories

I would like to figure out how this works, but I can't find a way to use this feature.

The only man page which seems vaguely relevant is clonefile(2), which says:

If src names a directory, the directory hierarchy is cloned as if each item was cloned individually. However, the use of copyfile(3) is more appropriate for copying large directory hierarchies instead of clonefile(2)

But when you check the man page for copyfile(3), it says:

Note also that there is no support for cloning directories: if a directory is provided as the source, an error will be returned. (This is only applicable for the copyfile() function.)

This is further clarified further down the page:

Because copyfile() does not allow the cloning of directories, a recursive clone will instead copy any directory it finds (while cloning its contents).

Nonetheless, a few blog posts on the subject seem to imply that Finder can perform this operation using option + mouse drag, but when I test it here, it seems identical to a recursive copy, and isn't even cloning the contained files, let alone the directory.

So what's the deal here? Is the feature implemented at all? If it is, how do I get it to work? Or is it something they implemented in the on-disk format but never hooked into any APIs or tools?


clonefile() is the system call that you're interested in. It was introduced in macOS 10.12 (Sierra), coinciding with the public beta release of APFS.

copyfile() is a C library function that was introduced in Mac OS X 10.5 (Leopard). As you have seen in the manpage, while it does support file cloning, this is not the default behaviour.

I am not sure why clonefile(2) states that "the use of copyfile(3) is more appropriate for copying large directory hierarchies instead of clonefile(2)" — I can only guess that it is for efficiency reasons. Regardless, both APIs will allow you to clone files without duplicating any file extents on disk.

I can confirm that, at least for me, macOS 10.15 (Catalina) does clone large files when "copying" them in Finder, whether using CMD-C and CMD-V, or ALT-drag-and-drop. The same is true for directories, in the sense described in clonefile(2). That is, all directories involved are copied (new inodes and dentries will appear on disk), and all files involved are cloned.

It's worth noting that, in order to comply with POSIX, cp is required to make non-clone copies (duplicate the file extents on disk), but using it with the -c flag will override this behaviour and clone files via clonefile() instead — see cp(1). The behaviour is identical to that of the Linux cp flag --reflink, which you might be familiar with if you use ZFS or similar.

Thus, cp -Rc is what you're looking for if you want to clone directories on the terminal. I am not sure when this flag was introduced, but it was likely alongside the release of clonefile() in macOS 10.12. According to this talk (1.28 GB MP4 file) by Tim Standing, this has at least been the case in public releases of macOS since January 2018.