应使用 lsblk -n | awk '{print $1}' | grep -e '^sd|^nvme|^vd' | grep -v '[0-9]\|loop\|zram' | sort -u 提取纯净物理磁盘名,再通过 while ifs= read -r dev 安全遍历,避免 for 循环解析错误。

用 lsblk -n 提取干净的设备名,关键在于过滤掉非磁盘行、去重并排除伪设备(如 loop、zram)。默认输出含多列,需精准提取第一列且避免误判。
只取第一列 + 去除非物理/块设备行
lsblk -n 输出无表头,但包含所有块设备(含分区、LVM、loop 等)。脚本中应:
- 用
awk '{print $1}'提取设备名(首列) - 加
grep -E '^sd|^nvme|^vd|^hd'限制常见物理磁盘前缀(根据实际硬件调整) - 排除分区(带数字后缀)和已挂载的伪设备:可追加
| grep -v '[0-9]|loop|zram|md'
去重 + 排序(防重复扫描同一磁盘)
同一磁盘可能因分区、LVM、multipath 出现多次。加 sort -u 保证每个底层设备只出现一次:
- 例如:
lsblk -n | awk '{print $1}' | grep -E '^sd|^nvme' | grep -v '[0-9]' | sort -u - 注意:
nvme0n1p1是分区,nvme0n1才是磁盘 —— 所以先去分区再取基名更稳妥
在 for 循环中安全使用
直接管道进 for 易受空格或换行符干扰。推荐用 while read 或命令替换:
- 安全写法:
while IFS= read -r dev; do echo "处理设备: /dev/$dev" # 你的操作,如 smartctl -a /dev/$dev done - 避免用
for dev in $(...),防止设备名含空格或特殊字符时出错
补充:跳过只读/不可用设备(可选)
若需进一步过滤,可用 lsblk -n -o NAME,RO,RM,TYPE 多列输出,再筛选:
lsblk -n -o NAME,RO,RM,TYPE | awk '$2==0 && $3==1 && $4=="disk" {print $1}'- 其中
RO==0表示非只读,RM==1表示可移动(如 USB),TYPE=="disk"确保是整盘而非分区











