以下非常不健壮的shell代码将给出$path
的挂载点:
(for i in $(df|cut -c 63-99); do case $path in $i*) echo $i;; esac; done) | tail -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;; esac; done| tail -1 /sys
在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;; esac; done| tail -1 /dev
注意需要改变切割参数,因为df的输出方式不同;使用awk解决了这个问题,但即使是awk也是不可移植的,给定了结果格式化df返回的各种实现。
答案 看起来munging表格输出是shell中的唯一方法,但是
df -P "$path" | tail -1 | awk '{ print $NF}'
基于ghostdog74的回答,对我所拥有的是一个很大的改进。请注意两个新问题:首先,df $path
坚持$path
命名现有文件,我上面的脚本并不关心;其次,不用担心解除引用符号链接。如果您的挂载点中包含空格,则无法执行此操作,如果其中包含可移动媒体,其卷名称中包含空格,则会出现这种情况。
编写Python代码以正确完成工作并不困难。
答案 0 :(得分:17)
df
将路径作为参数,因此像这样的东西应该相当健壮;
df "$path" | tail -1 | awk '{ print $6 }'
答案 1 :(得分:14)
理论上stat
会告诉你文件所在的设备,应该有一些方法将设备映射到挂载点。
例如,在linux上,这应该有效:
stat -c '%m' $path
答案 2 :(得分:6)
一直喜欢使用程序的格式化选项,因为它比操作输出更强大(例如,如果挂载点有空格)。 GNU df
允许以下内容:
df --output=target "$path" | tail -1
不幸的是,我无法看到阻止打印标题的选项,因此仍需要尾部。
答案 3 :(得分:1)
我不知道你想要的输出是什么,因此这是一个猜测
#!/bin/bash
path=/home
df | awk -v path="$path" 'NR>1 && $NF~path{
print $NF
}'
使用带-c的cut并不是真的可靠,因为df的输出会有所不同,比如说5%可以改为10%而你会错过一些字符。由于挂载点始终位于后面,因此您可以使用字段和字段分隔符。在上面,$ NF是最后一列,也就是挂载点。
答案 4 :(得分:1)
我会将源代码发送到df并找出它除了调用stat
之外的其他功能,正如Douglas Leeder建议的那样。
df
输出的逐行解析将导致问题,因为这些行通常看起来像
/dev/mapper/VOLGROUP00-logical--volume
1234567 1000000 200000 90% /path/to/mountpoint
由于增加了解析这些行的复杂性,可能调用stat
并找到挂载点也不那么复杂。
答案 5 :(得分:1)
也有同样的问题。如果某些挂载点(或已挂载的设备)足以满足我的要求,您可以执行以下操作:
DEVNO=$(stat -c '%d' /srv/sftp/testconsumer)
MP=$(findmnt -n -f -o TARGET /dev/block/$((DEVNO/2**8)):$((DEVNO&2**8-1)))
(或用 %D
分割十六进制DEVNO /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表示readlink。)
答案 6 :(得分:0)
mount | grep "^$path" | awk '{print $3}'
答案 7 :(得分:0)
当我查看之前的问题时,我错过了这个问题:Python: Get Mount Point on Windows or Linux,其中os.path.ismount(path)
表示路径是否为挂载点。
我的偏好是shell解决方案,但这看起来很简单。
答案 8 :(得分:0)
我用这个:
df -h $path | cut -f 1 -d " " | tail -1
答案 9 :(得分:0)
Linux有这个,这将避免空格问题:
lsblk -no MOUNTPOINT ${device}
不确定BSD的土地。
答案 10 :(得分:0)
f () { echo $6; }; f $(df -P "$path" | tail -n 1)
答案 11 :(得分:0)
如果你只想使用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,但应该适用于任何发行版。