I am looking for a quick way to find the mount point of the file system containing a given FILE. Is there anything simpler or more direct than my solution below?
df -h FILE |tail -1 | awk -F% '{print $NF}' | tr -d ' '
A similar question “Is there a command to see where a disk is mounted?” uses the current disk’s device node as input, and not an arbitrary file from the disk …
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
On GNU/Linux, if you have GNU stat from coreutils 8.6 or above, you could do:
stat -c %m -- "$file"
Otherwise:
mount_point_of() {
f=$(readlink -e -- "$1") &&
until mountpoint -q -- "$f"; do
f=${f%/*}; f=${f:-/}
done &&
printf '%sn' "$f"
}
Your approach is valid but assumes the mount point doesn’t contain space, %, newline or other non-printable characters, you can simplify it slightly with newer versions of GNU df (8.21 or above):
df --output=target FILE | tail -n +2
Method 2
For Linux we have findmnt from util-linux exactly made for this
findmnt -n -o TARGET --target /path/to/FILE
Note that some kind of random mountpoint may be returned in case there are several bind mounts. Using df has the same problem.
Method 3
You could do something like
df -P FILE | awk 'NR==2{print $NF}'
or even
df -P FILE | awk 'END{print $NF}'
Since awk splits on whitespace(s) by default, you don’t need to specify the -F and you also don’t need to trim the whitespace with tr. Finally, by specifying the line number of interest (NR==2) you can also do away with tail.
Method 4
Since stat returns a “Device” field, I was curious to see how the underlying stat() library call could be used to get this information programmatically in a POSIX compliant way.
This snippet of C code:
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
int main (int argc, const char *argv[]) {
struct stat info;
stat(argv[1], &info);
printf("min: %d maj: %dn",
minor(info.st_dev),
major(info.st_dev)
);
return 0;
}
Will give the major and minor devices ID’s for the device containing the file listed on the command line (argv[1]). Unfortunately, major() and minor() aren’t POSIX, although the man page claims they are “present on many other systems ” besides GNU/linux.
You can then get a correspondence between the device major/minor number and the device node from, e.g., /proc/diskstats, and map that to mount points from /proc/mounts, aka. /etc/mtab.
So a command-line utility to do this would be pretty simple.
Method 5
Here’s more C++ code if you want to do this from C++…
#include <boost/filesystem.hpp>
#include <sys/stat.h>
/// returns true if the path is a mount point
bool Stat::IsMount(const std::string& path)
{
if (path == "") return false;
if (path == "/") return true;
boost::filesystem::path path2(path);
auto parent = path2.parent_path();
struct stat sb_path;
if (lstat(path.c_str(), &sb_path) == -1) return false; // path does not exist
if (!S_ISDIR(sb_path.st_mode)) return false; // path is not a directory
struct stat sb_parent;
if (lstat(parent.string().c_str(), &sb_parent) == -1 ) return false; // parent does not exist
if (sb_path.st_dev == sb_parent.st_dev) return false; // parent and child have same device id
return true;
}
/// returns the path to the mount point that contains the path
std::string Stat::MountPoint(const std::string& path0)
{
// first find the first "real" part of the path, because this file may not exist yet
boost::filesystem::path path(path0);
while(!boost::filesystem::exists(path) )
{
path = path.parent_path();
}
// then look for the mount point
path = boost::filesystem::canonical(path);
while(! IsMount(path.string()) )
{
path = path.parent_path();
}
return path.string();
}
More links for programmatic ways
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0