Note: please give feedback on the title, I honest didn't know how to title this question.
Im trying to design a code that everytime the user drop a file in the tools
folder, it automatic gets add into the main code at menu.sh
script, so it's simpler for the user.
The menu.sh is working fine, but everytime the user adds a new script he needs to do add two lines of code in the main script(menu.sh
)
for example, lets say the user want to add a script called run-scrape.sh
"run-scrape" need to be added:
-options variable
-added in the source command inside the case statment
I am trying to automate this two tasks so it's simpler for the user.
I am open to a different approach to do this or link to something similar, I couldn't find anything like.
Background:
folder structure:
~
scripts
menu.sh, tools
> cd tools
pushing-code.sh, purge-data.sh, run-scrape.sh
menu.sh :
title="title"
prompt="Pick an option(number): "
options=(
"pushing code" \
"purge-data" \
"run-scrape" \
)
echo "$title"
PS3="$prompt"
select opt in "${options[@]}" "Quit"; do
case "$REPLY" in
0) source $(pwd)/scripts/tools/pushing-code.sh; my_func;;
0) source $(pwd)/scripts/tools/purge-data.sh; my_func;;
0) source $(pwd)/scripts/tools/run-scrape.sh; my_func;;
$((${#options[@]} 1))) echo "Goodbye!"; break;;
*) echo "Invalid option. Try another one.";continue;;
esac
Working the Solution:
basically some how need to create this two components in the menu.sh code:
The variable: options
myFileNames=$(ls ~/$(pwd)/scripts/tools) for file in $myFileNames;
The case statement
the following line of code will be the same for every file except for the file name, in this example: pushing-code.shso adding this to the menu.sh code:
#sample: 0) source $(pwd)/scripts/tools/pushing-code.sh; my_func; path=$(pwd) args=() for i in myFileNames; do args=("0) source $path/scripts/tools/$i ; my_func;") done select opt in "${options[@]}" "Quit"; do case "$REPLY" in args $((${#options[@]} 1))) echo "Goodbye!"; break;; *) echo "Invalid option. Try another one.";continue;; esac
I don't think it's well put together, does anyone have done something similar in the past that would share the code :)
CodePudding user response:
1: The variable: options
myFileNames=$(ls ~/$(pwd)/scripts/tools) for file in $myFileNames;
- Use pathname expansion (globbing), not
ls
. - And use it to populate an array, not a flat string. Also
~/$(pwd)/scripts/tools
does not make sense.- If you want to assume that the working directory contains
scripts/
as a subdirectory then just use a relative path (scripts/tools
). - If you want to give a path relative to your home directory then use
~/literal/path/to/scripts/tools
- If you want a path relative to the location of the script then see How do I get the directory where a Bash script is located from within the script itself?
- If you want to assume that the working directory contains
Overall, something along these lines
# Create an array of all the *.sh files in the tools directory
options=(/path/to/tools/*.sh)
You can check the result by, for example,
echo "${options[@]}"
2: The case statement the following line of code will be the same for every file except for the file name, in this example: pushing-code.sh
Having the options in an array, you can access each one via its index. That pairs nicely with using select
, something along these lines:
# Select from among elements of the options array
select choice in "${options[@]}"; do
if [[ -n "$choice" ]]; then
# read and evaluate the commands from the selected file
# select options are numbered from 1, but array indices from 0
source "${options[$((choice - 1))]}"
break
else
echo "$REPLY" is not a valid selection
# ...
fi
done
The select
command will automatically loop until a break
command is executed or EOF is reached on the standard input.