macOS - Archive/Restore Library
Complete archive and restore scripts are available in scripts/apple-books.
What To Archive/Restore?
Apple Books for macOS stores its data in two locations:
~/Library/Containers/com.apple.BKAgentService
~/Library/Containers/com.apple.iBooksX
See macOS - Library Location for more information.
However, archiving and restoring only these directories might miss some metadata. Searching
~/Library/Containers
for anything that contains Books
yields some other directories:
find ~/Library/Containers -type d -name "*Books*"
./com.apple.BKAgentService/Data/Documents/iBooks
./com.apple.BKAgentService/Data/Documents/iBooks/Books
./com.apple.iBooksX
./com.apple.iBooksX/Data/Documents/BCCloudKit-iBooks
./com.apple.iBooksX/Data/Documents/BCCloudAsset-iBooks
./com.apple.iBooksX/Data/Documents/BKBookstore
./com.apple.iBooksX/Data/Library/Caches/com.apple.iBooksX
./com.apple.iBooksX.CacheDelete
./com.apple.iBooksX.DiskSpaceEfficiency
./com.apple.iBooksX.SharingExtension
./com.apple.iBooksX-SecureUserDefaults
Using BK
as a proxy for Books
yields no additional directories:
find ~/Library/Containers -type d -name "*BK*"
./com.apple.BKAgentService
./com.apple.iBooksX/Data/Documents/BKSeriesDatabase
./com.apple.iBooksX/Data/Documents/BKLibraryDataSourceDevelopment
./com.apple.iBooksX/Data/Documents/BKLibrary
./com.apple.iBooksX/Data/Documents/BKBookstore
So it's safe to assume any directory starting with com.apple.Books
or com.apple.BK
is important.
Therefore, these two globs along with Apple Books' Group Container
should be used for archiving
and restoring:
"~/Library/Containers/com.apple.BK*"
"~/Library/Containers/com.apple.iBooks*"
"~/Library/Group Containers/group.com.apple.iBooks"
Important Note
Archiving/restoring will work only if the path to the username has not changed since the
library was archived. Doing a few searches shows that the username has been hard-coded into some
files. This is most evident in the BKLibrary-*.sqlite
file which contains absolute paths to
library files.
For example:
find "~/Library/Containers/com.apple.BKAgentService" \
-type f -a -exec grep -l --exclude=\*.{htm,html,xhtml} $USER {} +
.../.com.apple.containermanagerd.metadata.plist
.../Container.plist
.../Data/Documents/iBooks/Books/Books.plist
find "~/Library/Containers/com.apple.iBooksX*" \
-type f -a -exec grep -l --exclude=\*.{htm,html,xhtml} $USER {} +
.../com.apple.iBooksX/.com.apple.containermanagerd.metadata.plist
.../com.apple.iBooksX/Container.plist
.../com.apple.iBooksX/Data/Documents/BKLibrary/BKLibrary-1-091020131601.sqlite-wal
.../com.apple.iBooksX/Data/Documents/BKLibrary/BKLibrary-1-091020131601.sqlite
.../com.apple.iBooksX-SecureUserDefaults/.com.apple.containermanagerd.metadata.plist
.../com.apple.iBooksX-SecureUserDefaults/Container.plist
.../com.apple.iBooksX.CacheDelete/.com.apple.containermanagerd.metadata.plist
.../com.apple.iBooksX.CacheDelete/Container.plist
.../com.apple.iBooksX.DiskSpaceEfficiency/.com.apple.containermanagerd.metadata.plist
.../com.apple.iBooksX.DiskSpaceEfficiency/Container.plist
.../com.apple.iBooksX.SharingExtension/.com.apple.containermanagerd.metadata.plist
.../com.apple.iBooksX.SharingExtension/Container.plist
Archive Library
The following snippet is taken from scripts/apple-books/macos-archive.sh.
Archiving the library is as simple as running two rsync
commands. This should save all
the relevant Apple Books data and metadata to a single directory. Make sure to replace
[PATH-TO-ARCHIVE]
with a valid path to said directory.
rsync \
--archive \
--extended-attributes \
"$HOME/Library/Containers/com.apple.BK*" \
"$HOME/Library/Containers/com.apple.iBooks*" \
"[PATH-TO-ARCHIVE]/Containers"
rsync \
--archive \
--extended-attributes \
"$HOME/Library/Group Containers/group.com.apple.iBooks" \
"[PATH-TO-ARCHIVE]/Group Containers"
For example, if [PATH-TO-ARCHIVE]
is:
~/archives/2022-10-08--apple-books-v4.4-5177--macos-v12.6
Our rsync
commands would be:
rsync \
--archive \
--extended-attributes \
"$HOME/Library/Containers/com.apple.BK*" \
"$HOME/Library/Containers/com.apple.iBooks*" \
"~/archives/2022-10-08--apple-books-v4.4-5177--macos-v12.6/Containers"
rsync \
--archive \
--extended-attributes \
"$HOME/Library/Group Containers/group.com.apple.iBooks" \
"~/archives/2022-10-08--apple-books-v4.4-5177--macos-v12.6/Group Containers"
And the resulting archive would resemble:
~/archives
└── 2022-10-08--apple-books-v4.4-5177--macos-v12.6
├── Containers
│ ├── com.apple.BKAgentService
│ ├── com.apple.iBooks.BooksNotificationContentExtension
│ ├── com.apple.iBooks.engagementExtension
│ ├── com.apple.iBooks.iBooksSpotlightExtension
│ ├── com.apple.iBooksX
│ ├── com.apple.iBooksX-SecureUserDefaults
│ ├── com.apple.iBooksX.BooksThumbnail
│ ├── com.apple.iBooksX.CacheDelete
│ ├── com.apple.iBooksX.DiskSpaceEfficiency
│ └── com.apple.iBooksX.SharingExtension
└── Group Containers
└── group.com.apple.iBooks
Restore Library
The following snippets are taken from scripts/apple-books/macos-restore.sh.
When restoring a library make sure that the current version of Apple Books for macOS and the version the archive was created from are identical. Not doing so could lead to unexpected results.
Restoring the library takes an extra step. First we need to clear out the current Apple Books library. We can delete all the library files and directories by using the paths we determined from What To Archive/Restore?.
rm -rf "$HOME/Library/Containers/com.apple.BK*"
rm -rf "$HOME/Library/Containers/com.apple.iBooks*"
rm -rf "$HOME/Library/Group Containers/group.com.apple.iBooks"
Finally, we can run the reverse rsync
commands and restore the archive we previously made. Make
sure to replace [PATH-TO-ARCHIVE]
with a valid path.
rsync \
--archive \
--extended-attributes \
"[PATH-TO-ARCHIVE]/Containers/" \
"$HOME/Library/Containers/"
rsync \
--archive \
--extended-attributes \
"[PATH-TO-ARCHIVE]/Group Containers/" \
"$HOME/Library/Group Containers/"
The trailing forward-slash after
Containers
andGroup Containers
here is important. It tellsrsync
to move the archive directory's contents into the target. Otherwise, it would move the archive directory into the target.
For example, if [PATH-TO-ARCHIVE]
is:
~/archives/2022-10-08--apple-books-v4.4-5177--macos-v12.6
Our rsync
command would be:
rsync \
--archive \
--extended-attributes \
"~/archives/2022-10-08--apple-books-v4.4-5177--macos-v12.6/Containers/" \
"$HOME/Library/Containers/" # Note the forward-slash! --------------^
rsync \
--archive \
--extended-attributes \
"~/archives/2022-10-08--apple-books-v4.4-5177--macos-v12.6/Group Containers/" \
"$HOME/Library/Group Containers/" # Note the forward-slash! --------------^