I surely hope there's an easier way. Still, if all else fails:
I've never used it, but the timecopy Python script (for use with faulty Time Machine backups) might help. It's a long script but it seems it's not only that long just because of Time Machine. And especially its support for faulty disks can be useful for your corrupted file system too. From its website:
Using a tool that performs a block-for-block copy will in fact copy the file system error to the new disk, which is of no use at all. What's needed is a way to copy the file system to a new location using traditional file copy. The only problem with that is the Time Machine backups are full of hard links, which will appear as normal files and directories, and performing a simple file copy will result in an enormous waste of disk space.
It supports a --dry-run option, and --verbose outputs nice mkdir, cp, ln and ln -s commands.
The script enforces using the Time Machine Backups.backupdb file structure. It seems to me that changing srcdb = os.path.join(srcbase, 'Backups.backupdb') into srcdb = srcbase, and also changing dstdb = os.path.join(dstbase, 'Backups.backupdb') into dstdb = dstbase, might make this usable for non-TM sources.
It then processes each sub folder of the source folder, expecting each to be a machine name, being the root of all backups for that machine (typically one, unless the disk is used for multiple computers). Within each sub folder, it processes everything except for files named .DS_Store, Latest or ending with .inProgress. But: it does not expect the sub folders of the source folder to be hard links themselves. If you do have hard links in the source folder, then maybe you can mount the disk with an extra folder name. Like: use /Volumes/my/mount rather than /Volumes/mount, and then run timecopy for the source folder /Volumes/my.
Finally, it will also create a symbolic link named Latest, just as a Time Machine disk would, for the most recent sub folder. You can of course delete that afterwards.
You can then still do the --dry-run, or maybe the output of --verbose --dry-run can help to get a script that you can use in some other way?