我正在重构一个显示与此类似的文本菜单的脚本:
Select a mounted BTRFS device on your local machine to backup to.
1) 123456789abc-def012345-6789abcdef012 (/)
2) 123456789abc-def012345-6789abcdef012 (/home)
...
26) 3e3456789abc-def012345-6789abcdef369 (/mnt/backup2)
27) 223456789abc-def012345-6789abcdef246 (/mnt/backup3)
请注意,该菜单显示两项信息:UUID 和目标路径。使用命令复制它select
是我不知道该怎么做的事情之一。
在此菜单中,用户输入数字(例如 26),脚本执行 BTRFS 发送|接收到该设备和路径。我希望脚本菜单继续以相同的方式工作,即显示 UUID 加路径并采用简单的 1 或 2 位数字或字符输入。
但是,我想重构代码。原来的代码不是我写的。它使用两个数组来显示菜单并处理选择。
我想使用关联数组。这纯粹是我获得关联数组经验的一个练习。该脚本按原样运行。
我想使用我编写的以下代码作为菜单的基础:
declare -A UUID_TARGETS
for target in $TARGETS; do
if ! [[ "$target" =~ ^/mnt|^/backup ]] ; then
echo "skipped $target"
else
UUID_TARGETS["$target"]=$(findmnt -n -t btrfs -o UUID -M "$target")
fi
done
for target in "${!UUID_TARGETS[@]}"; do
#testing
echo UUID [${UUID_TARGETS["$target"]}] has mountpoint [$target]
done
bashselect
命令似乎没有生成我想要的菜单,因为我需要在菜单中显示两项信息:UUID 和目标路径。像这样天真的使用select
还不够:
PS3="Please enter your choice (q to quit): "
select target in "${!UUID_TARGETS[@]}" "quit";
do
case "$target" in
"quit")
echo "Exited"
break
;;
*)
selected_uuid=${UUID_TARGETS["$target"]}
selected_mnt="$target"
;;
esac
done
我希望这里有人从关联数组制作这样的菜单的优雅解决方案。我想在 bash 中执行此操作,而不需要额外的软件包。
最后,我仍然需要为selected_uuid
和分配正确的值selected_mnt
。原来的代码是这样实现的:
selected_uuid="${UUIDS_ARRAY[$((disk))]}"
selected_mnt="${TARGETS_ARRAY[$((disk))]}"
作为参考,这里是原始代码的整个部分:
TARGETS="$(findmnt -n -l -t btrfs -o TARGET --list -F /etc/fstab)"
UUIDS="$(findmnt -n -l -t btrfs -o UUID --list -F /etc/fstab)"
declare -a TARGETS_ARRAY
declare -a UUIDS_ARRAY
i=0
disk=-1
disk_count=0
for x in $UUIDS; do
UUIDS_ARRAY[$i]=$x
if [[ "$x" == "$uuid_cmdline" ]]; then
disk=$i
disk_count=$(($disk_count+1))
fi
i=$((i+1))
done
i=0
for x in $TARGETS; do
TARGETS_ARRAY[$i]=$x
i=$((i+1))
done
if [[ "$disk_count" > 1 ]]; then
disk="-1"
fi
if [[ "$disk" == -1 ]]; then
if [[ "$disk_count" == 0 && "$uuid_cmdline" != "none" ]]; then
error "A device with UUID $uuid_cmdline was not found to be mounted, or it is not a BTRFS device."
fi
if [[ -z $ssh ]]; then
printf "Select a mounted BTRFS device on your local machine to backup to.\n"
else
printf "Select a mounted BTRFS device on $remote to backup to.\n"
fi
while [[ $disk -lt 0 || $disk -gt $i ]]; do
for x in "${!TARGETS_ARRAY[@]}"; do
printf "%4s) %s (%s)\n" "$((x+1))" "${UUIDS_ARRAY[$x]}" "${TARGETS_ARRAY[$x]}"
done
printf "%4s) Exit\n" "0"
read -r -p "Enter a number: " disk
if ! [[ $disk == ?(-)+([0-9]) ]]; then
printf "\nNo disk selected. Select a disk to continue.\n"
disk=-1
fi
done
if [[ $disk == 0 ]]; then
exit 0
fi
disk=$(($disk-1))
fi
selected_uuid="${UUIDS_ARRAY[$((disk))]}"
selected_mnt="${TARGETS_ARRAY[$((disk))]}"
printf "\nYou selected the disk with UUID %s.\n" "$selected_uuid" | tee $PIPE
printf "The disk is mounted at %s.\n" "$selected_mnt" | tee $PIPE