例如,我有一个文件,其路径如下:
/media/my_mountpoint/path/to/file.txt
我已经有整个路径,并想要获取:
/media/my_mountpoint
我应该如何做到这一点?最好使用Python并且不使用外部库/工具。(两者都不是必需的。)
/media/my_mountpoint/path/to/file.txt
我已经有整个路径,并想要获取:
/media/my_mountpoint
我应该如何做到这一点?最好使用Python并且不使用外部库/工具。(两者都不是必需的。)
你可以调用 mount
命令并解析其输出以找到与你的路径最长公共前缀,或使用 stat
系统调用获取文件所驻留的设备,并向上遍历树直到达到不同的设备。
在 Python 中,stat
可以如下使用(未经测试,可能需要扩展以处理符号链接和像联合挂载这样的奇异东西):
def find_mount_point(path):
path = os.path.abspath(path)
orig_dev = os.stat(path).st_dev
while path != '/':
dir = os.path.dirname(path)
if os.stat(dir).st_dev != orig_dev:
# we crossed the device border
break
path = dir
return path
编辑:我刚刚才知道os.path.ismount
。这极大地简化了事情。
def find_mount_point(path):
path = os.path.abspath(path)
while not os.path.ismount(path):
path = os.path.dirname(path)
return path
由于Python不是必需的:
df "$filename" | awk 'NR==1 {next} {print $6; exit}'
NR==1 {next}
的作用是跳过 df 命令输出的标题行。 $6
是挂载点。 exit
作用在于保证我们只输出一行。-P
标志进行兼容 POSIX 输出时才能正常工作。对于常规输出,如果路径过长,则文件系统列将单独显示在一行中,并且所有其他列值都会在下一行中显示。 - David Leuschner由于现在在使用UUID
或LABEL
挂载文件系统的系统中,无法可靠地解析mount
的内容,因为输出可能会包含以下内容:
(...)
/dev/disk/by-uuid/00000000-0000-0000-0000-000000000000 on / type ext4 (rw,relatime,errors=remount-ro,data=ordered)
(...)
stat
命令来发现文件所在的挂载点,如下所示:$ stat --printf "%h:%m:%i\n" Talks
6:/media/lattes:461246
def find_mount_point(path):
if not os.path.islink(path):
path = os.path.abspath(path)
elif os.path.islink(path) and os.path.lexists(os.readlink(path)):
path = os.path.realpath(path)
while not os.path.ismount(path):
path = os.path.dirname(path)
if os.path.islink(path) and os.path.lexists(os.readlink(path)):
path = os.path.realpath(path)
return path
@larsmans 的答案很好,非常有帮助!我在 Golang 中实现了这个功能。
对于那些对代码感兴趣的人(这已经在 OS X 和 Linux 上测试过):
package main
import (
"os"
"fmt"
"syscall"
"path/filepath"
)
func Mountpoint(path string) string {
pi, err := os.Stat(path)
if err != nil {
return ""
}
odev := pi.Sys().(*syscall.Stat_t).Dev
for path != "/" {
_path := filepath.Dir(path)
in, err := os.Stat(_path)
if err != nil {
return ""
}
if odev != in.Sys().(*syscall.Stat_t).Dev {
break
}
path = _path
}
return path
}
func main() {
path, _ := filepath.Abs("./")
dir := filepath.Dir(path)
fmt.Println("Path", path)
fmt.Println("Dir", dir)
fmt.Println("Mountpoint", Mountpoint(path))
}
export PATH_TO_LOOK_FOR="/media/path";
perl -ne '@p = split /\s+/; print "$p[1]\n" if "'$PATH_TO_LOOK_FOR'" =~ m@^$p[1]/@' < /proc/mounts
注意在$PATH_TO_LOOK_FOR周围加上" ' ' ",否则它将无法工作。
//编辑:Python解决方案:
def find_mountpoint(path):
for l in open("/proc/mounts", "r"):
mp = l.split(" ")[1]
if(mp != "/" and path.find(mp)==0): return mp
return None
os.path.realpath
移除符号链接,因此这样更简洁:
def find_mountpoint(path):
"""Find the non-symlinked mountpoint of a path."""
path = os.path.realpath(path)
while not os.path.ismount(path):
path = os.path.dirname(path)
return path
/bin/mountpoint [-q] [-d] /path/to/directory
import os
def find_mount_point(path):
while not os.path.ismount(path):
path=os.path.dirname(path)
return path
abspath()
调用。 - Georg Schölly
os.path.ismount()
。我认为可能有比沿着路径遍历更直接的方法。 - Georg Schöllyos.path.abspath()
替换为os.path.realpath()
,或者find_mount_point()
将返回“/”。 - insecure