如何找到文件所在的挂载点?

2024-11-14 08:29:00
admin
原创
16
摘要:问题描述:例如,我有一个具有以下路径的文件:/media/my_mountpoint/path/to/file.txt 我已经获得了完整的路径并想要获得:/media/my_mountpoint 我该怎么做?最好使用 Python,并且不使用外部库/工具。(两者都不是必需的。)解决方案 1:您可以调用该mou...

问题描述:

例如,我有一个具有以下路径的文件:

/media/my_mountpoint/path/to/file.txt

我已经获得了完整的路径并想要获得:

/media/my_mountpoint

我该怎么做?最好使用 Python,并且不使用外部库/工具。(两者都不是必需的。)


解决方案 1:

您可以调用该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

解决方案 2:

由于 python 不是必需的:

df "$filename" | awk 'NR==1 {next} {print $6; exit}'

NR==1 {next}跳过 df 输出的标题行。$6是挂载点。exit是为了确保我们只输出一行。

解决方案 3:

由于现在我们无法真正可靠地解析由或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
" Talks
6:/media/lattes:461246

在上面的输出中,我们可以看到:

  • 中的硬链接数 ( %h)Talks为 6

  • 挂载点 ( %m) 是/media/lattes

  • 它的 inode 编号 ( %i) 为 461246。

仅供参考,这是stat来自 GNU coreutils的版本,这意味着某些其他版本(例如 BSD)可能默认没有它(但您始终可以使用您喜欢的包管理器安装它)。

解决方案 4:

@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))
}

解决方案 5:

我正在用 Python 开发 GTK+ 3 文件管理器,在循环遍历文件时遇到了同样的需求。

我使用的计算机有 Linux 和 OS X 分区。当文件管理器应用程序(在 Linux 根分区上运行)尝试索引 OS X 分区上的文件时,它很快就会遇到从“/media/mac-hd/User Guides And Information”到“/Library/Documentation/User Guides 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.abspath()os.path.realpath()find_mount_point()将返回“/”。

当我尝试用 替换时os.path.abspath(),我会得到os.path.realpath()的正确返回值。但是我还注意到,由于现在返回 ,因此在调用时我将不再获得我想要的值。/run`/var/runfind_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

解决方案 6:

我的 python 已经生疏了,不过你可以在 perl 中使用类似这样的命令:

export PATH_TO_LOOK_FOR="/media/path";
perl -ne '@p = split /s+/; print "$p[1]
" 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

解决方案 7:

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

解决方案 8:

/bin/mountpoint [-q] [-d] /path/to/directory

解决方案 9:

import os

def find_mount_point(path):
    while not os.path.ismount(path):
        path=os.path.dirname(path)
    return path
相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   601  
  华为IPD与传统研发模式的8大差异在快速变化的商业环境中,产品研发模式的选择直接决定了企业的市场响应速度和竞争力。华为作为全球领先的通信技术解决方案供应商,其成功在很大程度上得益于对产品研发模式的持续创新。华为引入并深度定制的集成产品开发(IPD)体系,相较于传统的研发模式,展现出了显著的差异和优势。本文将详细探讨华为...
IPD流程是谁发明的   7  
  如何通过IPD流程缩短产品上市时间?在快速变化的市场环境中,产品上市时间成为企业竞争力的关键因素之一。集成产品开发(IPD, Integrated Product Development)作为一种先进的产品研发管理方法,通过其结构化的流程设计和跨部门协作机制,显著缩短了产品上市时间,提高了市场响应速度。本文将深入探讨如...
华为IPD流程   9  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程图是连接创意、设计与市场成功的桥梁。它不仅是一个视觉工具,更是一种战略思维方式的体现,帮助团队高效协同,确保产品按时、按质、按量推向市场。尽管IPD流程图可能初看之下显得错综复杂,但只需掌握几个关键点,你便能轻松驾驭...
IPD开发流程管理   8  
  在项目管理领域,集成产品开发(IPD)流程被视为提升产品上市速度、增强团队协作与创新能力的重要工具。然而,尽管IPD流程拥有诸多优势,其实施过程中仍可能遭遇多种挑战,导致项目失败。本文旨在深入探讨八个常见的IPD流程失败原因,并提出相应的解决方法,以帮助项目管理者规避风险,确保项目成功。缺乏明确的项目目标与战略对齐IP...
IPD流程图   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用