From the discussion in the comments it is apparent that your main concern is to create as script with multiple selections, rather than focus on copying/moving files themselves, and the file operations are just an example. This functionality can be achieved via dialog
command, which allows creating text user interfaces, with --checklist
flag specifically; however there's nothing in the standard shell-only toolbox to achieve what you want. Hence, dialog
is an appropriate tool for this job.
Below you will find an example script. While the script implements only 3
options that were discussed, it provides a decent starting point which users can extent further, and also addresses mutually exclusive options as mentioned in the comments. Particularly, the multiple selection is addressed in menu()
function, which serves as a wrapper for dialog
with --checklist
option
To keep things simple, all you really need is this:
output=$(dialog --clear --backtitle "Backtitle. Use <SPACE> to select." --title "My Dialog" \
--checklist "Select all that apply" 50 50 100 \
checksum "SHA-256" off \
copy "Copy only (exclusive with move)" off \
move "Move only (exclusive with copy)" off 2>&1 > /dev/tty)
This saves the selection of multiple items to variable $output
. Note that `2>&1 > /dev/tty) at the end are crucial to saving the return value into variable. But see the script below for more practical example:
#!/bin/bash
puke(){
# function to exit with specific error message
# analogous to 'die' in Perl
printf ">>> Errors were encountered: %s\n" "$1" && exit
} > /dev/stderr
menu(){
# dialog --help documents the option as follows:
# --checklist <text> <height> <width> <list height> <tag1> <item1> <status1>...
# tags are what the output returns.
# We can use word-splitting
# and iterate over output of this function in order. Of course first option
# being checksum will always work and is not mutually exclusive with anything else
dialog --clear --backtitle "Backtitle. Use <SPACE> to select." --title "My Dialog" \
--checklist "Select all that apply" 50 50 100 \
checksum "SHA-256" off \
copy "Copy only (exclusive with move)" off \
move "Move only (exclusive with copy)" off || puke
} 2>&1 1>/dev/tty
select_file(){
dialog --backtitle "Choose file by typing or navigating and selecting with <SPACE>" --fselect "/etc/" \
20 50 || puke
} 2>&1 1>/dev/tty
iter_actions(){
# variables are available to child functions
# Since we call iter_actions in main(), this
# function also knows about main's variable $fselect
for i ; do
case "$i" in
checksum) sha256sum "$fselect" ;;
copy) cp "$fselect" /tmp ;;
move) mv "$fselect" /tmp ;;
esac
done
}
main(){
# here I'm using /etc but you can use $PWD to default to user's
# current working directory, or accept positional parameters from command-line
# as in $1, $2 and so forth
fselect=$( select_file "/etc" )
actions=$(menu)
printf "\r%b" "\033c" # this clear the screen
case "$actions" in
*copy*move|*move*copy) puke "Mutually exclusive options selected" ;;
*) iter_actions $actions ;; # note here variable is unquoted on purpose
esac
}
# script entry point
main "$@"
For further research:
Best Answer
Just remove (I would prefer with force option enabled) the file -
$i
:;
sign.Another option is to move the file to the trash instead of delete it:
In addition, your script can be improved in the following way:
Here is one related question: Script to merge Video and subs then delete the existing files