lsblk -n -o NAME,SIZE,TYPE /dev/sd* 2>/dev/null 适用于 cmd 行,不在脚本文件中

Posted

技术标签:

【中文标题】lsblk -n -o NAME,SIZE,TYPE /dev/sd* 2>/dev/null 适用于 cmd 行,不在脚本文件中【英文标题】:lsblk -n -o NAME,SIZE,TYPE /dev/sd* 2>/dev/null works on cmd line, not in script file 【发布时间】:2021-11-01 11:08:14 【问题描述】:

我正在编写一个脚本来检测和格式化 Raspberry Pi 的 USB 驱动器。我让脚本完美地适用于通过 USB 适配器插入的 sd 卡。当我尝试使用 USB3 硬盘时它失败了。隔离失败表示脚本中的通配符扩展和重定向处理存在问题。

当我执行 lsblk -n -o NAME,SIZE,TYPE /dev/sd* 2>/dev/null

在根终端中,输出为空,没有任何 USB 设备,插入时为空:

sda     3.7G disk
└─sda1  3.7G part
sda1    3.7G part

当我在脚本中以这种方式运行它时:

#!/bin/bash
xtra='/dev/sd* 2>/dev/null'
DETECTOR="lsblk -n -o NAME,SIZE,TYPE $xtra"

zenity --info --text="Remove all USB devices" --width=620 --height=200
not_in=$($DETECTOR)
zenity --info --text="Insert USB device to format" --width=420 --height=100
usb_in=$($DETECTOR)

# Get the difference which is inserted USB device and partitions on it
delta=$(diff <(echo "$not_in") <(echo "$usb_in"))
drive=($delta//[^[:ascii:]]/)  # Delete the non-ASCII characters

echo -e "$not_in\n$usb_in\n\n$drive[@]\n\n$delta"

得到的是:

lsblk: /dev/sd*: not a block device
lsblk: 2>: not a block device
lsblk: /dev/null: not a block device
lsblk: 2>: not a block device
lsblk: /dev/null: not a block device

sda     3.7G disk
└─sda1  3.7G part
sda1    3.7G part

1c1,3 < --- > sda 3.7G disk > sda1 3.7G part > sda1 3.7G part

1c1,3
< 
---
> sda     3.7G disk
> └─sda1  3.7G part
> sda1    3.7G part

我不明白如何在数组变量 ($drive) 中仅获取插入的设备及其分区。 lsblk 命令的解释方式与 bash 正确扩展 sd* 并将 stderr 指向 /dev/null 的命令行调用以及它在脚本上下文中的运行方式有所不同。

我已经阅读了与不同 shell 如何解释通配符和重定向相关的类似问题,但这仅涉及 bash。

我能想出的唯一解决方法是创建临时文件,这既不优雅也不吸引人:

【问题讨论】:

不要尝试将命令存储在变量中(例如DETECTOR);变量用于数据,而不是可执行代码或 shell 语法。要么直接使用命令,要么将其放入函数而不是变量中。见BashFAQ #50: I'm trying to put a command in a variable, but the complex cases always fail! 【参考方案1】:
#!/bin/bash
DETECTOR="lsblk -n -o NAME,SIZE,TYPE /dev/sd*"

zenity --info --text="Remove all USB devices" --width=620 --height=200
$DETECTOR > noSD 2>/dev/null
zenity --info --text="Insert USB device to format" --width=420 --height=100
$DETECTOR > sdIn 2>/dev/null

# Get the difference which is inserted USB device and partitions on it
delta=$(diff noSD sdIn | tr -d \> | grep sd)
drive=($delta//[^[:ascii:]]/)  # Delete the non-ASCII characters

not_in=$(cat noSD)
usb_in=$(cat sdIn)
echo -e "Not in:$not_in\nIn:$usb_in\n\nArray:$drive[@]\n\nDiff:\n$delta"

【讨论】:

请添加更多详细信息以扩展您的答案,例如工作代码或文档引用。

以上是关于lsblk -n -o NAME,SIZE,TYPE /dev/sd* 2>/dev/null 适用于 cmd 行,不在脚本文件中的主要内容,如果未能解决你的问题,请参考以下文章

5数组:为什么很多编程语言中数组都从0开始编号?

centos怎么使用命令查看硬盘sn

磁盘分区与挂载

lsblk命令

linux产看磁盘信息命令-lsblk,blkid

MySQL--lsblk命令查看块设备