树莓派USB格式化脚本中lsblk命令执行异常问题咨询
问题根因
你遇到的错误本质是Bash命令解析顺序的问题:
Bash解析命令的优先级是:先处理重定向、通配符展开,再执行变量替换。你把/dev/sd* 2>/dev/null放到字符串变量xtra中,后续执行$DETECTOR时,变量替换得到的内容会被全部当成lsblk的参数,不会再解析其中的重定向规则,也不会对通配符做展开,所以lsblk会把/dev/sd*、2>、/dev/null都当成要查询的块设备路径,自然就报错了。
修复后的完整脚本
#!/bin/bash # 定义USB设备检测函数 get_usb_devices() { # 开启nullglob:通配符无匹配时返回空数组,而非返回通配符本身 shopt -s nullglob local sd_devs=(/dev/sd*) shopt -u nullglob # 无匹配设备时直接返回空 if [ ${#sd_devs[@]} -eq 0 ]; then return fi # 正常调用lsblk,重定向直接写在命令中 lsblk -n -o NAME,SIZE,TYPE "${sd_devs[@]}" 2>/dev/null } zenity --info --text="Remove all USB devices" --width=620 --height=200 not_in=$(get_usb_devices) zenity --info --text="Insert USB device to format" --width=420 --height=100 usb_in=$(get_usb_devices) # 提取新增设备,直接过滤diff结果中>开头的新增行,丢弃diff格式符号 # 以下是两种常用提取方式,按需选择: # 1. 仅提取设备名存入数组 drive=($(diff <(echo "$not_in") <(echo "$usb_in") | grep '^>' | sed 's/^> *//' | awk '{print $1}')) # 2. 保留完整的设备信息(名称、大小、类型)存入数组,每行一个元素 # mapfile -t drive < <(diff <(echo "$not_in") <(echo "$usb_in") | grep '^>' | sed 's/^> *//') # 测试输出 echo "===== 无设备时输出 =====" echo "$not_in" echo -e "\n===== 插入设备后输出 =====" echo "$usb_in" echo -e "\n===== 新增设备数组内容 =====" printf "%s\n" "${drive[@]}"
关键调整说明
- 弃用字符串存储命令的写法,改用Bash函数封装检测逻辑,符合Bash的解析规则,通配符、重定向都能正常生效
- 增加
nullglob选项处理无USB设备的场景,避免通配符无匹配时直接把/dev/sd*字符串传给lsblk - 优化新增设备提取逻辑,直接过滤diff的输出结果,避免多余的非ASCII符号(如树结构的└─字符)和diff格式符污染数组内容
- 若需要保留每行完整的设备信息,可使用
mapfile按行存入数组,避免空格拆分问题
内容的提问来源于stack exchange,提问作者Thomas Loves Tech
相关产品推荐
相关产品推荐

