#!/bin/bash die() { printf "%s: Error: %s\n" "$0" "$*" >&2; exit 1; } ECHO() { printf "%s\n" "$*" >&2; } PRINTF() { printf "$@" >&2; } whole_device() { case "$1" in *-part?) false ;; *-part??) false ;; *-part???) false ;; */usb\*) false ;; *) true ;; esac } confirm_usb_strict() { CONFIRM_MSG="This will completely overwrite device:\n\n\t%s\n\nType 'yes' to confirm.\nContinue? " CONFIRM_WITH_ONE_LETTER= confirm_helper "$@" } confirm_usb_lax() { CONFIRM_MSG="The device used will be:\n\n\t%s\n\nType 'y' to confirm.\nContinue? " CONFIRM_WITH_ONE_LETTER=y confirm_helper "$@" } confirm_helper() { PRINTF "$CONFIRM_MSG" "$1" read line case "$line" in [yY][eE][sS]) return ;; [yY]) [ "$CONFIRM_WITH_ONE_LETTER" ] && return || : ;; esac die "Aborted by user." } choose_usb() { local devs maj USB set -- /dev/disk/by-id/usb* for dev; do shift whole_device "$dev" || continue set -- "$@" "$dev" done if [ $# = 0 ]; then die "no USB storage device found" elif [ $# = 1 ]; then [ "$NO_ACT" ] && confirm=confirm_usb_lax || confirm=confirm_usb_strict $confirm "$1" || exit USB=$1 else ECHO PRINTF "%s\n" "The following candidate target devices have been found:" i=0 for dev; do i=$((i+1)) PRINTF "\n\n\t%2i. %s\n" $i "$dev" done PRINTF "%s\n\n" '' "Choose a device by its number, from 1 to $#, then press enter." "To abort, press CTRL-C." PRINTF "\n%s" 'Your choice: ' read line case "$line" in [1-9]|[1-9][0-9]) [ $line -le $# -a $line -ge 1 ] || die "Invalid argument (out of range): $line" USB=${!line} ;; *) die "Invalid argument: $line" ;; esac confirm_usb_lax fi [ "$USB" ] && readlink -f "$USB" } NO_ACT= case "$1" in -n) NO_ACT=y;; -*) exit 1;; esac choose_usb