开发者

Give the mount point of a path

开发者 https://www.devze.com 2022-12-18 08:43 出处:网络
The following, very non-robust shell code will give the mount point of $path: (for i in $(df|cut -c 63-99); do case $path in $i*) echo $i;; esac; done) | tail -n 1

The following, very non-robust shell code will give the mount point of $path:

 (for i in $(df|cut -c 63-99); do case $path in $i*) echo $i;; esac; done) | tail -n 1

Is there a better way to do this in shell?

Postscript

This script is really awful, but has the redeeming quality that it Works On My Systems. Note that several mount points may be prefixes of $path.

Examples On a Linux system:

cas@txtproof:~$ path=/sys/block/hda1
cas@txtproof:~$ for i in $(df -a|cut -c 57-99); do case $path in $i*) echo $i;; esac; done| tail -1
/sys

On a Mac OSX system

cas local$ path=/dev/fd/0
cas local$ for i in $(df -a|cut -c 63-99); do case $path in $i*) echo $i;; esac; done| tail -1
/dev

Note the need 开发者_StackOverflow中文版to vary cut's parameters, because of the way df's output differs; using awk solves this, but even awk is non-portable, given the range of result formatting various implementations of df return.

Answer It looks like munging tabular output is the only way within the shell, but

df -P "$path"  | tail -1 | awk '{ print $NF}'

based on ghostdog74's answer, is a big improvement on what I had. Note two new issues: firstly, df $path insists that $path names an existing file, the script I had above doesn't care; secondly, there are no worries about dereferencing symlinks. This doesn't work if you have mount points with spaces in them, which occurs if one has removable media with spaces in their volume names.

It's not difficult to write Python code to do the job properly.


df takes the path as parameter, so something like this should be fairly robust;

df "$path" | tail -1 | awk '{ print $6 }'


In theory stat will tell you the device the file is on, and there should be some way of mapping the device to a mount point.

For example, on linux, this should work:

stat -c '%m' $path


Always been a fan of using formatting options of a program, as it can be more robust than manipulating output (eg if the mount point has spaces). GNU df allows the following:

df --output=target "$path" | tail -1

Unfortunately there is no option I can see to prevent the printing of a header, so the tail is still required.


i don't know what your desired output is, therefore this is a guess

#!/bin/bash

path=/home
df | awk -v path="$path" 'NR>1 && $NF~path{
 print $NF
}'

Using cut with -c is not really reliable, since the output of df will be different , say a 5% can change to 10% and you will miss some characters. Since the mount point is always at the back, you can use fields and field delimiters. In the above, $NF is the last column which is the mount point.


I would take the source code to df and find out what it does besides calling stat as Douglas Leeder suggests.

Line-by-line parsing of the df output will cause problems as those lines often look like

/dev/mapper/VOLGROUP00-logical--volume
                      1234567  1000000  200000  90% /path/to/mountpoint

With the added complexity of parsing those kinds of lines as well, probably calling stat and finding the mountpoint is less complex.


If you want to use only df and awk to find the filesystem device/remote share or a mount point and they include spaces you can cheat by defining the field separator of awk to be a regular expression that matches the format of the numeric sizes used to display total size, used space, available space and capacity percentage. By defining those columns as the field separator you are then left with $1 representing the filesystem device/remote share and $NF representing the mount path.

Take this for example:

[root@testsystem ~] df -P
Filesystem                       1024-blocks        Used Available Capacity Mounted on
192.168.0.200:/NFS WITH SPACES   11695881728 11186577920 509303808      96% /mnt/MOUNT WITH SPACES

If you attempt to parse this with the quick and dirty awk '{print $1}' or awk '{print $NF}' you'll only get a portion of the filesystem/remote share path and mount path and that's no good. Now make awk use the four numeric data columns as the field separator.

[root@testsystem ~] df -P "/mnt/MOUNT WITH SPACES/path/to/file/filename.txt" | \
awk 'BEGIN {FS="[ ]*[0-9]+%?[ ]+"}; NR==2 {print $1}'
192.168.0.200:/NFS WITH SPACES

[root@testsystem ~] df -P "/mnt/MOUNT WITH SPACES/path/to/file/filename.txt" | \
awk 'BEGIN {FS="[ ]*[0-9]+%?[ ]+"}; NR==2 {print $NF}'
/mnt/MOUNT WITH SPACES

Enjoy :-)

Edit: These commands are based on RHEL/CentOS/Fedora but should work on just about any distribution.


Just had the same problem. If some mount point (or the mounted device) is sufficent as in my case You can do:

DEVNO=$(stat -c '%d' /srv/sftp/testconsumer)
MP=$(findmnt -n -f -o TARGET /dev/block/$((DEVNO/2**8)):$((DEVNO&2**8-1)))

(or split the hex DEVNO %D with /dev/block/$((0x${DEVNO:0:${#DEVNO}-2})):$((0x${DEVNO:2:2})))

Alternatively the following loop come in to my mind, out of ideas why I cannot find proper basic command..

TARGETPATH="/srv/sftp/testconsumer"
TARGETPATHTMP=$(readlink -m "$TARGETPATH")
[[ ! -d "$TARGETPATHTMP" ]] && TARGETPATHTMP=$(dirname "$TARGETPATH")
TARGETMOUNT=$(findmnt -d backward -f -n -o TARGET --target "$TARGETPATHTMP")
while [[ -z "$TARGETMOUNT" ]]
do
  TARGETPATHTMP=$(dirname "$TARGETPATHTMP")
  echo "$TARGETPATHTMP"
  TARGETMOUNT=$(findmnt -d backward -f -n -o TARGET --target "$TARGETPATHTMP")
done

This should work always but is much more then I expect for such simple task?

(Edited to use readlink -f to allow for non existing files, -m or -e for readlink could be used instead if more components might not exists or all components must exists.)


mount | grep "^$path" | awk '{print $3}'


I missed this when I looked over prior questions: Python: Get Mount Point on Windows or Linux, which says that os.path.ismount(path) tells if path is a mount point.

My preference is for a shell solution, but this looks pretty simple.


I use this:

df -h $path | cut -f 1 -d " " | tail -1


Linux has this, which will avoid problem with spaces:

lsblk -no MOUNTPOINT ${device}

Not sure about BSD land.


f () { echo $6; }; f $(df -P "$path" | tail -n 1)
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号