![macOS:du 可能会报告错误的磁盘使用大小吗?](https://linux22.com/image/108283/macOS%EF%BC%9Adu%20%E5%8F%AF%E8%83%BD%E4%BC%9A%E6%8A%A5%E5%91%8A%E9%94%99%E8%AF%AF%E7%9A%84%E7%A3%81%E7%9B%98%E4%BD%BF%E7%94%A8%E5%A4%A7%E5%B0%8F%E5%90%97%EF%BC%9F.png)
我有一个脚本正在我的卷上的某些位置进行测试,其中一部分是磁盘使用情况和总数据大小的计算。一切都很好,我得到的值总是与 macOS 本身在输出mdls
和 Finder 信息中报告的值相匹配。
然而,当在 Homebrew 安装目录上运行脚本时/usr/local/Cellar
,输出很奇怪。磁盘使用量以3,234,828,288
字节为单位,而数据大小实际上更大,即以字节为3,254,656,870
单位。以 root 身份或使用 GNU-du 运行脚本时会得到相同的结果。磁盘使用率不应该总是高于数据大小吗? (当然,除非您使用 HFS+ 压缩,但这里的情况似乎并非如此:输出中没有“压缩”文件标志ls
。)
以下是脚本的相关部分,首先是磁盘使用情况,然后是数据总量:
FILEPATH="/usr/local/Cellar"
DISK_USAGE=$(/usr/bin/du -k -d 0 "$FILEPATH" | /usr/bin/head -n 1 | /usr/bin/awk '{print $1}')
DU_SIZE=$(echo "$DISK_USAGE * 1024" | /usr/bin/bc -l)
SEDPATH=$(echo "$FILEPATH" | /usr/bin/awk '{gsub("/","\\/");print}')
LISTING=$(ls -RAlO@ "$FILEPATH" | /usr/bin/sed -e '/^$/d' -e '/^'"$SEDPATH"'/d' | /usr/bin/awk 'NF>2')
DATASIZE=$(echo "$LISTING" | /usr/bin/grep -v '^d' | /usr/bin/awk '{total += $6} END {printf "%.0f", total}')
echo "du: $DU_SIZE"
echo "data: $DATASIZE"
可能的解决方案:macOS 和 HFS+ 是问题所在,一如既往!我相信他们称之为“苹果核心腐烂”。我再次运行 du 命令,以及计算总数据大小的脚本,还添加了一些命令来根据 ls/stat 输出中的块计数“手动”计算磁盘使用情况,你瞧,计算出的磁盘使用情况实际上大于总数据大小,因为它应该没有 FS 压缩(稀疏文件等),现在(突然间!)du 命令也输出了正确的结果。为什么我只能猜测,但这可能是因为 HFS+ 一开始就没有时间计算它,所以当 du 询问系统“磁盘使用情况是多少”时,它只得到了部分结果。
FILEPATH="/usr/local/bin" [21:38:27]
SEDPATH=$(echo "$FILEPATH" | /usr/bin/awk '{gsub("/","\\/");print}')
MPOINT=$(/bin/df "$FILEPATH" | /usr/bin/tail -1 | /usr/bin/awk '{for(i=9; i<=NF; i++) printf "%s",$i (i==NF?ORS:OFS)}')
CLUSTERSIZE=$(/usr/sbin/diskutil info "$MPOINT" | /usr/bin/awk '/Device Block Size/{print $4}')
TOTAL_LIST=$(ls -ReAlOs@ "$FILEPATH")
SWITCH_LIST=$(echo "$TOTAL_LIST" | /usr/bin/sed -e '/^$/d' -e '/^'"$SEDPATH"'/d' | /usr/bin/awk 'NF>=11' | /usr/bin/awk '{print $2,$7,$1}')
BLOCKSONDISK=$(echo "$SWITCH_LIST" | /usr/bin/grep -v '^d' | /usr/bin/awk '{total += $3} END {printf "%.0f", total}')
SIZEONDISK=$(echo "$BLOCKSONDISK * $CLUSTERSIZE" | /usr/bin/bc -l)
echo "od: $SIZEONDISK B"
DISK_USAGE=$(/usr/bin/du -k -d 0 "$FILEPATH" | /usr/bin/head -n 1 | /usr/bin/awk '{print $1}')
DU_SIZE=$(echo "$DISK_USAGE * 1024" | /usr/bin/bc -l)
echo "du: $DU_SIZE B"
DATASIZE=$(echo "$SWITCH_LIST" | /usr/bin/grep -v '^d' | /usr/bin/awk '{total += $2} END {printf "%.0f", total}')
echo "ds: $DATASIZE B"
输出:
physical (stat): 36343808 B
physical (du): 36343808 B
datasize (stat): 32584254 B