例如,我有一个文件,路径如下:
/media/my_mountpoint/path/to/file.txt
字符串我已经得到了整个路径,我想得到:
/media/my_mountpoint
型我该怎么做呢?最好是用Python,不使用外部库/工具。(两者都不是必需的。)
wvyml7n51#
您可以调用mount命令并解析其输出,以找到路径中最长的公共前缀,或者使用stat系统调用来获取文件所在的设备,然后沿着树向上查找,直到到达另一个设备。在Python中,stat可以按如下方式使用(未经测试,可能需要扩展以处理符号链接和union mounts之类的外来内容):
mount
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
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的,这大大简化了事情。
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
while not os.path.ismount(path):
path = os.path.dirname(path)
型
yacmzcpb2#
由于Python不是必需的:
df "$filename" | awk 'NR==1 {next} {print $6; exit}'
字符串NR==1 {next}用于跳过df输出的标题行。$6是挂载点。exit用于确保我们只输出一行。
NR==1 {next}
$6
exit
mnemlml83#
由于现在我们无法在UUID或LABEL挂载文件系统的系统中真正可靠地解析mount的内容,因为输出可能包含以下内容:
UUID
LABEL
(...)/dev/disk/by-uuid/00000000-0000-0000-0000-000000000000 on / type ext4 (rw,relatime,errors=remount-ro,data=ordered)(...)
(...)
/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" Talks6:/media/lattes:461246
$ stat --printf "%h:%m:%i\n" Talks
6:/media/lattes:461246
型在上面的输出中,我们可以看到:
Talks
%h
%m
/media/lattes
%i
只是为了记录,这是与来自GNU coreutils的stat版本一起使用的,这意味着其他一些版本(例如BSD)可能默认没有它(但您可以始终使用首选的包管理器安装它)。
l2osamch4#
@larsmans非常好的回答,这是非常有帮助的!我已经在Golang中实现了这一点,我需要它。对于那些对代码感兴趣的人(这已经在OS X和Linux上测试过了):
package mainimport ( "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))}
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 odev != in.Sys().(*syscall.Stat_t).Dev {
path = _path
func main() {
path, _ := filepath.Abs("./")
dir := filepath.Dir(path)
fmt.Println("Path", path)
fmt.Println("Dir", dir)
fmt.Println("Mountpoint", Mountpoint(path))
ds97pgxw5#
我在Python中使用GTK+ 3文件管理器,在循环文件时遇到了同样的需求。我使用的计算机有Linux和OS X分区。(运行在根Linux分区上)将尝试索引OSX分区上的文件,它会很快遇到一个从“/media/mac-hd/UserGuides And Information”到“/Library/Documentation/UserGuides and Information.localized”的绝对符号链接问题是文件管理器在自己的文件系统上寻找该链接的绝对目标,而不是在/media/mac-hd安装的OS X分区上。所以,我需要一种方法来确定文件位于不同的挂载点上,并将该挂载点预挂到链接的绝对目标上。我从Fred Foo的答案中编辑的解决方案开始。它似乎有助于为我试图解决的特定错误提供解决方案。当我调用find_mount_point('/media/mac-hd/User Guides And Information')时,它会返回/media/mac-hd。太好了,我想。我注意到insecure在答案下面关于使用符号链接的评论,也注意到他关于/var/run的评论是正确的:为了让你的代码可以使用符号链接,例如/var/run ->../run,用os.path.realpath()替换os.path.abspath(),否则find_mount_point()将返回“/"。当我尝试用os.path.realpath()替换os.path.abspath()时,我会得到/var/run的正确的/run返回值。但是我也注意到,我在调用find_mount_point('/media/mac-hd/User Guides And Information')时不再得到我想要的值,因为它现在返回/。以下是我最终使用的解决方案。也许它可以简化:
find_mount_point('/media/mac-hd/User Guides And Information')
/media/mac-hd
os.path.realpath()
os.path.abspath()
find_mount_point()
/var/run
/run
/
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
if not os.path.islink(path):
elif os.path.islink(path) and os.path.lexists(os.readlink(path)):
path = os.path.realpath(path)
if os.path.islink(path) and os.path.lexists(os.readlink(path)):
dy1byipe6#
我的python是rusty,但你可以使用这样的东西与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
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解决方案:
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
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
aurhwmvo7#
os.path.realpath删除了符号链接,因此更简洁:
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
"""Find the non-symlinked mountpoint of a path."""
j2cgzkjk8#
/bin/mountpoint [-q] [-d] /path/to/directory
yqhsw0fo9#
import osdef find_mount_point(path): while not os.path.ismount(path): path=os.path.dirname(path) return path
import os
path=os.path.dirname(path)
9条答案
按热度按时间wvyml7n51#
您可以调用
mount
命令并解析其输出,以找到路径中最长的公共前缀,或者使用stat
系统调用来获取文件所在的设备,然后沿着树向上查找,直到到达另一个设备。在Python中,
stat
可以按如下方式使用(未经测试,可能需要扩展以处理符号链接和union mounts之类的外来内容):字符串
编辑:我也是刚刚才知道
os.path.ismount
的,这大大简化了事情。型
yacmzcpb2#
由于Python不是必需的:
字符串
NR==1 {next}
用于跳过df输出的标题行。$6
是挂载点。exit
用于确保我们只输出一行。mnemlml83#
由于现在我们无法在
UUID
或LABEL
挂载文件系统的系统中真正可靠地解析mount
的内容,因为输出可能包含以下内容:字符串
我们需要一个更健壮的解决方案(例如,考虑一下像上面这样的路径的“切割”部分可能导致什么,以及我们是否想要这样的东西)。
一个这样的解决方案(顺便说一句,它试图不重新发明轮子)是简单地使用
stat
命令来发现文件所在的挂载点,如下所示:型
在上面的输出中,我们可以看到:
Talks
中的硬链接(%h
)的数量是6%m
)为/media/lattes
%i
)是461246。只是为了记录,这是与来自GNU coreutils的
stat
版本一起使用的,这意味着其他一些版本(例如BSD)可能默认没有它(但您可以始终使用首选的包管理器安装它)。l2osamch4#
@larsmans非常好的回答,这是非常有帮助的!我已经在Golang中实现了这一点,我需要它。
对于那些对代码感兴趣的人(这已经在OS X和Linux上测试过了):
字符串
ds97pgxw5#
我在Python中使用GTK+ 3文件管理器,在循环文件时遇到了同样的需求。
我使用的计算机有Linux和OS X分区。(运行在根Linux分区上)将尝试索引OSX分区上的文件,它会很快遇到一个从“/media/mac-hd/UserGuides And Information”到“/Library/Documentation/UserGuides and Information.localized”的绝对符号链接问题是文件管理器在自己的文件系统上寻找该链接的绝对目标,而不是在/media/mac-hd安装的OS X分区上。所以,我需要一种方法来确定文件位于不同的挂载点上,并将该挂载点预挂到链接的绝对目标上。
我从Fred Foo的答案中编辑的解决方案开始。它似乎有助于为我试图解决的特定错误提供解决方案。当我调用
find_mount_point('/media/mac-hd/User Guides And Information')
时,它会返回/media/mac-hd
。太好了,我想。我注意到insecure在答案下面关于使用符号链接的评论,也注意到他关于/var/run的评论是正确的:
为了让你的代码可以使用符号链接,例如/var/run ->../run,用
os.path.realpath()
替换os.path.abspath()
,否则find_mount_point()
将返回“/"。当我尝试用
os.path.realpath()
替换os.path.abspath()
时,我会得到/var/run
的正确的/run
返回值。但是我也注意到,我在调用find_mount_point('/media/mac-hd/User Guides And Information')
时不再得到我想要的值,因为它现在返回/
。以下是我最终使用的解决方案。也许它可以简化:
字符串
dy1byipe6#
我的python是rusty,但你可以使用这样的东西与perl:
字符串
注意$PATH_TO_LOOK_FOR周围的 ”",否则它将无法工作。
//edit:python解决方案:
型
aurhwmvo7#
os.path.realpath
删除了符号链接,因此更简洁:字符串
j2cgzkjk8#
字符串
yqhsw0fo9#
字符串