例如,我有一个包含以下路径的文件:
/media/my_mountpoint/path/to/file.txt
我已经走完了整条道路,想要得到:
/media/my_mountpoint
我该怎么做?最好是在Python中,不使用外部库/工具。 (两者都不是必需的。)
答案 0 :(得分:17)
您可以调用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
答案 1 :(得分:5)
因为python不是必需的:
df "$filename" | awk 'NR==1 {next} {print $6; exit}'
NR==1 {next}
是跳过df输出的标题行。 $6
是挂载点。 exit
是为了确保我们只输出一行。
答案 2 :(得分:4)
由于现在我们无法真正可靠地解析由mount
或UUID
挂载文件系统的系统中LABEL
的内容,因为输出可能包含以下内容:
(...)
/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
在上面的输出中,我们可以看到:
%h
中的硬链接数(Talks
)为6 %m
)为/media/lattes
%i
)为461246。仅供记录,这是来自GNU coreutils的stat
版本,这意味着其他一些版本(例如BSD)默认情况下可能没有它(但你可以随时使用您首选的包管理器安装它。)
答案 3 :(得分:2)
我正在使用Python中的GTK + 3文件管理器,在循环浏览文件时遇到了同样的需求。
我正在使用的计算机有Linux和OS X分区。当文件管理器应用程序(在根Linux分区上运行)尝试索引OS X分区上的文件时,它会很快遇到从“/ media / mac-hd /用户指南和信息”到“/”的绝对符号链接图书馆/文献/用户指南和信息。本地化“和扼流圈。问题是文件管理器在它自己的文件系统上寻找该链接的绝对目标,而不是在/ media / mac-hd上安装的OS X分区。因此,我需要一种方法来识别文件位于不同的挂载点上,并将该挂载点预先添加到链接的绝对目标。
我从 Fred Foo 的回答开始编辑解决方案。它似乎有助于为我试图解决的具体错误提供解决方案。当我打电话给find_mount_point('/media/mac-hd/User Guides And Information')
时,它会返回/media/mac-hd
。很好,我想。
我注意到不安全的评论下面的答案是关于如何使用符号链接,并且还注意到他对/ var / run是正确的:
使您的代码与符号链接一起使用,例如/ var / run - > ../run,将
os.path.abspath()
替换为os.path.realpath()
或find_mount_point()
将返回“/”。
当我尝试用os.path.abspath()
替换os.path.realpath()
时,我会为/run
获得/var/run
的正确返回值。但是我也注意到在调用find_mount_point('/media/mac-hd/User Guides And Information')
时我不再获得我想要的值,因为它现在返回/
。
以下是我最终使用的解决方案。也许它可以简化:
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
答案 4 :(得分:0)
我的python很生疏,但你可以使用perl这样的东西:
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周围的 “''” ,否则无效。
// edit:python solution:
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
答案 5 :(得分:0)
对于对代码感兴趣的人(已针对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))
}
答案 6 :(得分:-3)
/bin/mountpoint [-q] [-d] /path/to/directory
答案 7 :(得分:-3)
import os
def find_mount_point(path):
while not os.path.ismount(path):
path=os.path.dirname(path)
return path