我正在编写一个脚本来打印 ZFS 文件系统信息 - 目前处于测试阶段,但我收到了一个奇怪的错误。
我的初始脚本的相关部分如下:
zfs_human="$(zfs list | head -n 2 | tail -n 1)"
dfs_human="$(df -h | grep 'zfs' | head -n 1)"
zfs_usedh="$(echo $zfs_human | cut -d ' ' -f2)"
zfs_totah="$(echo $dfs_human | cut -d ' ' -f2)"
echo "$zfs_human"
echo "$dfs_human"
echo "$zfs_usedh"
echo "$zfs_totah"
给出以下输出:
zfs 2.31M 5.27T 34.4K /mnt/zfs
zfs 5.3T 128K 5.3T 1% /mnt/zfs
2.31M
5.3T
但是,当我运行时shellcheck
,它说我应该在命令替换中用双引号括住变量名,这是来自的输出shellcheck
:
In zfsspace.sh line 5:zfs_usedh="$(echo $zfs_human | cut -d ' ' -f2)" ^--------^
SC2086: Double quote to prevent globbing and word splitting.
Did you mean:
zfs_usedh="$(echo "$zfs_human" | cut -d ' ' -f2)"
In zfsspace.sh line 6:zfs_totah="$(echo $dfs_human | cut -d ' ' -f2)" ^--------^
SC2086: Double quote to prevent globbing and word splitting.
Did you mean:
zfs_totah="$(echo "$dfs_human" | cut -d ' ' -f2)"
然后我当然将我的代码更改为 shellcheck 的建议:
zfs_human="$(zfs list | head -n 2 | tail -n 1)"
dfs_human="$(df -h | grep 'zfs' | head -n 1)"
zfs_usedh="$(echo "$zfs_human" | cut -d ' ' -f2)"
zfs_totah="$(echo "$dfs_human" | cut -d ' ' -f2)"
echo "$zfs_human"
echo "$dfs_human"
echo "$zfs_usedh"
echo "$zfs_totah"
但现在输出是这样的:
zfs 2.31M 5.27T 34.4K /mnt/zfs
zfs 5.3T 128K 5.3T 1% /mnt/zfs
第 3 行和第 4 行是空白,这意味着按照 shellcheck 的建议,第 3 行和第 4 行命令替换不起作用,但在不引用我回显的变量时起作用。
我在 Ubuntu 20.04.1 上使用 Bash 5.0.17
有人能解释一下吗?谢谢。
答案1
添加-H
到 zfs 将删除标头并用单个制表符(而不是任意空格)分隔字段,这大大简化了解析。因为df
没有删除标头的选项,所以findmnt
这将是一个更好的选择。
#!/bin/bash
# zfs
read -r zfs_usedh < <(zfs list -H -o used)
# df
read -r zfs_totah < <(findmnt -frnt zfs -o size)
echo "$zfs_usedh"
echo "$zfs_totah"
没有总体规模,因此df
,您必须依靠传统数学。
#!/bin/bash
read -d \\n -r avail used total < <(zfs get -Hpo value available,used | \
awk 'NR < 3 { n+=$1; print $1 } END { print n }' | numfmt --invalid=ignore --to=iec \
)
printf %s\\n $used $total
答案2
根据@steeldrivers 的建议,我用 替换cut
,awk
并且它按预期工作。
zfs_human="$(zfs list | head -n 2 | tail -n 1)"
dfs_human="$(df -h | grep 'zfs' | head -n 1)"
zfs_usedh="$(echo "$zfs_human" | awk -F " " '{print $2}')"
zfs_totah="$(echo "$dfs_human" | awk -F " " '{print $2}')"
echo "$zfs_human"
echo "$dfs_human"
echo "$zfs_usedh"
echo "$zfs_totah"
为了保持一致性,我相信这是保留 推荐的语法的最佳解决方案shellcheck
,因此一致使用awk
进行cut
字符串拆分,除非有特殊原因需要使用cut
。