【问题标题】:Give the mount point of a path给出路径的挂载点
【发布时间】:2011-01-11 04:09:14
【问题描述】:

以下非常不可靠的 shell 代码将给出$path 的挂载点:

(for i in $(df|cut -c 63-99); do case $path in $i*) echo $i;;经社理事会;完成)|尾-n 1

有没有更好的方法在 shell 中做到这一点?

后记

这个脚本真的很糟糕,但它具有可在我的系统上运行的可取之处。请注意,几个挂载点可能是$path 的前缀。

示例 在 Linux 系统上:

cas@txtproof:~$ path=/sys/block/hda1 cas@txtproof:~$ for i in $(df -a|cut -c 57-99); do case $path in $i*) echo $i;;经社理事会;完成|尾-1 /系统

在 Mac OSX 系统上

cas local$ path=/dev/fd/0 cas local$ for i in $(df -a|cut -c 63-99); do case $path in $i*) echo $i;;经社理事会;完成|尾-1 /dev

注意需要改变 cut 的参数,因为 df 的输出方式不同;使用 awk 可以解决这个问题,但考虑到 df return 的各种实现的结果格式化范围,即使 awk 也是不可移植的。

回答 看起来修改表格输出是 shell 中的唯一方法,但是

df -P "$path" |尾-1 | awk '{ 打印 $NF}'

根据 ghostdog74 的回答,对我所拥有的东西有很大的改进。注意两个新问题:首先,df $path 坚持 $path 命名一个现有文件,我上面的脚本并不关心;其次,不用担心取消引用符号链接。如果您的挂载点中有空格,这将不起作用,如果一个可移动媒体的卷名中有空格,则会发生这种情况。

编写 Python 代码来正确完成这项工作并不难。

【问题讨论】:

标签: linux bash shell path mount


【解决方案1】:

刚刚遇到同样的问题。如果某个挂载点(或已挂载的设备)就我而言就足够了,您可以这样做:

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

(或将十六进制 DEVNO %D 拆分为 /dev/block/$((0x${DEVNO:0:${#DEVNO}-2})):$((0x${DEVNO:2:2}))

或者我想到了以下循环,为什么我找不到合适的基本命令..

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

这应该总是有效,但比我对如此简单任务的预期要多得多?

(编辑为使用readlink -f 以允许不存在的文件,如果更多组件可能不存在或所有组件都必须存在,则可以使用-m 或-e for readlink 代替。)

【讨论】:

  • 如果您在 Linux 上,那么 stat -c '%m' "$SOMEFILE" 应该可以工作。我不接受 Leeder 答案的原因是这个答案不可移植:BSD 系统对 stat 格式字符串有完全不同的语法。
  • @CharlesStewart 在最近的 linux 上可能是的。但不是在我们默认的仍然活着的 EL6 盒子上......
  • 啊,是的。我认为 GNU coreutils 在将 %m fmt 添加到 stat 之前添加了 --output 开关到 df:df --output=target "$SOMEFILE" 在那个系统上工作吗?
  • @CharlesStewart 目标在系统上不可用,但统计格式 %m 可用。只是 stat %m 确实返回 ? 而不是挂载点。但无论如何,是的,它可以通过非常牢不可破的 df 解析来完成,你是对的。但它错过了目标可能不存在的要求。这不是我的要求,所以我在防故障循环中错过了它。 (因此,如果它是存在的,您可以使用 @crashmaxed awk 解决方案,或者与 sed 或 bash 正则表达式类似的东西 [[ $(df -P /srv/sftp/testconsumer|tail -1) =~ ^.*\ +[0-9]+\ +[0-9]+\ +[0-9]+\ +[0-9]+%\ +(/.*)$ ]]; MOUNTPOINT=${BASH_REMATCH[1]}
【解决方案2】:

理论上stat 会告诉你文件所在的设备,并且应该有某种方法可以将设备映射到挂载点。

例如,在 linux 上,这应该可以工作:

stat -c '%m' $path

【讨论】:

  • 我喜欢这个建议,但在 mac os 10.4 上,对于大多数文件系统,运行 stat -f"%Sdr" 会返回 ???r
  • 我已经向 SU 发布了一个关于 macosx 行为的 qn:superuser.com/questions/103755/…
  • 太棒了!如果设备安装在带有空格的路径上,则此方法有效,而接受的答案失败。
  • @mavroprovato - 如果你在 Linux 上,这绝对是要走的路。不幸的是,包括 OSX/Darwin 在内的 BSD 对统计格式字符串有完全不同的语法。
【解决方案3】:

如果您只想使用 df 和 awk 来查找文件系统设备/远程共享或挂载点,并且它们包含空格,您可以通过将 awk 的字段分隔符定义为匹配数字格式的正则表达式来作弊用于显示总大小、已用空间、可用空间和容量百分比的大小。通过将这些列定义为字段分隔符,您将得到 $1 代表文件系统设备/远程共享和 $NF 代表挂载路径。

以此为例:

[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

如果您尝试使用快速而肮脏的awk '{print $1}'awk '{print $NF}' 来解析它,您将只能获得文件系统/远程共享路径和挂载路径的一部分,这是不好的。现在让 awk 使用四个数字数据列作为字段分隔符。

[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

享受:-)

编辑:这些命令基于 RHEL/CentOS/Fedora,但几乎适用于任何发行版。

【讨论】:

    【解决方案4】:
    f () { echo $6; }; f $(df -P "$path" | tail -n 1)
    

    【讨论】:

      【解决方案5】:

      一直喜欢使用程序的格式化选项,因为它比操作输出更健壮(例如,如果挂载点有空格)。 GNU df 允许:

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

      不幸的是,我没有看到阻止打印标题的选项,因此仍然需要尾部。

      【讨论】:

      • 使用--output=source获取挂载路径的块设备。
      【解决方案6】:

      Linux 有这个,可以避免空格问题:

      lsblk -no MOUNTPOINT ${device}
      

      不确定 BSD 领域。

      【讨论】:

      • 这并不能回答问题,因为它需要设备文件并且不适用于任何路径。
      【解决方案7】:

      我用这个:

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

      【讨论】:

        【解决方案8】:

        当我查看之前的问题时我错过了这个:Python: Get Mount Point on Windows or Linux,它说os.path.ismount(path) 告诉路径是否是一个安装点。

        我更喜欢 shell 解决方案,但这看起来很简单。

        【讨论】:

          【解决方案9】:
          mount | grep "^$path" | awk '{print $3}'
          

          【讨论】:

          • 这只会从设备文件中找到挂载点,lsblkfindmnt 更好。
          【解决方案10】:

          我会将源代码带到 df 并找出它除了像 Douglas Leeder 建议的那样调用 stat 之外的作用。

          df 输出的逐行解析会导致问题,因为这些行通常看起来像

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

          由于解析这些类型的行也增加了复杂性,可能调用stat 并找到挂载点就不那么复杂了。

          【讨论】:

            【解决方案11】:

            df 将路径作为参数,所以这样的东西应该是相当健壮的;

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

            【讨论】:

            • 正如 ndim 所说,这对我不起作用,因为 df 输出中的换行是由 LVM 名称引起的。 quota 命令有一个 --no-wrap 选项,但 df 似乎也没有。
            • df 具有不换行的 -P 选项。较新版本的 GNU df 根本不换行。
            • 值得记录的是,这不适用于路径中有空格的挂载点。我接受了这个答案,因为它是迄今为止给出的最好的答案,并且我的首选解决方案基于它。
            【解决方案12】:

            我不知道你想要的输出是什么,因此这是一个猜测

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

            使用 cut 和 -c 并不是很可靠,因为 df 的输出会有所不同,比如 5% 可以更改为 10%,你会错过一些字符。由于挂载点始终位于后面,因此您可以使用字段和字段分隔符。在上面,$NF 是挂载点的最后一列。

            【讨论】:

            • 是的,awk 比 cut 好,但我真的不想解析 df 的输出。请注意,挂载点是分层组织的。
            • 显示什么是 $path,并显示你想要的输出。在您的问题中提供尽可能多的信息。
            猜你喜欢
            • 2010-10-03
            • 2016-04-03
            • 1970-01-01
            • 1970-01-01
            • 2017-07-21
            • 1970-01-01
            • 2020-09-15
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多