I'm running macOS Big Sur and want to use the 'find' terminal command to search for filenames on my launch volume. The problem is the launch volume contains a folder named 'Volumes' which lists all mounted volumes. This causes 'find' to search all mounted disks when I want to limit the search to the launch volume. How do I construct a terminal command that limits the operation to only one mounted volume?
CodePudding user response:
For the volumes mounted under /Volumes, it's simple: use find -x. According to the man page:
-xPrevent find from descending into directories that have a device number different than that of the file from which the descent began.
But it's more complicated than that because starting in macOS Catalina (v10.15), what appears to be the system volume is actually a synthesis of two different volumes, a System volume containing immutable core OS files (mounted read-only), and a "Data" volume with all user data, configuration files, added software, etc. The filesystem root is the System volume, the Data volume is mounted at /System/Library/Volumes/Data, and "firmlinks" are used to make parts of the Data volume appear at relevant places in the filesystem (e.g. /Users is firmlinked to /System/Library/Volumes/Data/Users). There's more info on Ask Different here and here, and a detailed map at the Eclectic Light Company here.
Part of what makes this tricky is that the System and Data volumes have the same device number, so find -x treats them as the same volume and will cross from one to the other (including following firmlinks) without noticing. So for example if you search for something that's in your home folder, you may find the same file under both /Users/yourname and /System/Volumes/Data/Users/yourname. Depending on what you want, you may need to exclude /System/Volumes/Data to avoid these duplicate results. I think you can pretty much always exclude it by prefixing your normal search with -path /System/Volumes/Data -prune -false -o (unless you're doing a depth-first search). For example, to search the entire system for "myfile.txt" without duplicate results, you could use:
sudo find -x / -path /System/Volumes/Data -prune -false -o -name myfile.txt
(As I said, I think this will pretty much always work except for depth-first searches, but I could be wrong -- test it before you trust it.)
If you want to prevent find from following firmlinks... that's harder. I think you'll have to parse the list of firmlinks in /usr/share/firmlinks, and generate a pruning list from that.
There also appears to be a bug in find where it will find parts of the System volume under the Data volume(!). Here's an example showing a spurious second match to a file:
$ find -x / -name BridgeVersion.bin 2>/dev/null
/System/Library/CoreServices/BridgeVersion.bin
/System/Volumes/Data/System/Library/CoreServices/BridgeVersion.bin
$ ls /System/Volumes/Data/System/Library/CoreServices/BridgeVersion.bin
ls: /System/Volumes/Data/System/Library/CoreServices/BridgeVersion.bin: No such file or directory
I'm not really sure what to do about this one.
BTW, another thing you may run into is that the Transparency, Consent, and Control (TCC) privacy system (see here) and System Integrity Protection (SIP, see here) restrict access to many parts of the filesystem (independent of normal file permissions and root access), so you may need to grant access to whatever app find is running under, or turn off SIP, or just ignore a lot of permission errors.
