patternbashMinor
Bash manual page selection menu
Viewed 0 times
selectionmanualmenupagebash
Problem
I wrote the following script in the hopes of streamlining the finding and reading of multiple manual pages. Since I am always looking up different utilities' manual pages I thought this would a good learning aid.
One thing I should point out. My
#!/bin/bash
while true
do
echo
echo "1) /bin"
echo "2) /sbin"
echo "3) /usr/bin/"
echo "4) /usr/sbin"
echo "5) /usr/local/bin"
echo "6) /usr/local/lib"
echo "7) /usr/local/share"
echo "8) /usr/local/include"
echo "9) exit"
echo
read -p 'Select a directory ' d
if [[ $d = 1 ]]; then
dir=/bin
elif [[ $d = 2 ]]; then
dir=/sbin
elif [[ $d = 3 ]]; then
dir=/usr/bin
elif [[ $d = 4 ]]; then
dir=/usr/sbin
elif [[ $d = 5 ]]; then
dir=/usr/local/bin
elif [[ $d = 6 ]]; then
dir=/usr/local/lib
elif [[ $d = 7 ]]; then
dir=/usr/local/share
elif [[ $d = 8 ]]; then
dir=/usr/local/include
elif [[ $d = 9 ]]; then
exit
else
echo 'No such directory'
exit 1
fi
echo
while true
do
menu=( $(ls -1 ${dir}) )
i=0
for m in ${menu[@]}
do
echo "$(( i++ ))) $(basename $m)"
done | xargs -L3 | column -t
echo
echo 'Select from the list above'
echo 'Type b to go back to main menu'
read -p 'Type q to quit at anytime ' n
echo
if [[ $n = 'b' || $n = 'B' ]]; then
break 1
elif [[ $n = 'q' || $n = 'Q' ]]; then
exit
else
for item in ${menu[$n]}
do
if [[ $item =~ '.txt' ]]; then
item="$(echo ${item%.*})"
fi
man $item
done
fi
done
doneOne thing I should point out. My
/usr/local/bin directory has several .txt files. That is the reason for if [[ $item =~ '.txt' ]]; then item="$(echo ${item%.*})"; fi Maybe it is normal to have plain text filesSolution
Use a table driven menu
The menu to select from
A table-based approach would be more compact, easier to write and maintain.
Try to use an array, as you did in other places of the script.
First, put the directories in an array, for example:
Note that I added a dummy empty first element.
This is to make the 1-based indexes of your menu work with the 0-based array indexes.
Build the menu from this array using a counting loop from 1, the first non-empty element:
To validate the user input, simply check if
If yes, the input is invalid.
Security
Maybe it is normal to have plain text files in this directory or maybe this is something I did unintentionally when experimenting writing this script. (An earlier version of this script wrote all the man pages to plain text files.)
No, it is not normal to have
So I guess your earlier script put them there.
But a normal user should not have write access to these directories.
Which seems to suggest that you're playing with a privileged account,
possibly
That's a bad idea, avoid using
Simplify
You can simplify
Strangeness
You don't need the
When inside
In this code, I don't see why you need
It seems the value of
The menu to select from
/bin, /sbin and other is very repetitive.A table-based approach would be more compact, easier to write and maintain.
Try to use an array, as you did in other places of the script.
First, put the directories in an array, for example:
dirs=('' /bin /sbin /usr/bin) # fill the restNote that I added a dummy empty first element.
This is to make the 1-based indexes of your menu work with the 0-based array indexes.
Build the menu from this array using a counting loop from 1, the first non-empty element:
for ((index = 1; index < ${#dirs[@]}; index++)); do
echo "$index) ${dirs[$index]}"
doneTo validate the user input, simply check if
${dirs[$index]} is empty.If yes, the input is invalid.
Security
Maybe it is normal to have plain text files in this directory or maybe this is something I did unintentionally when experimenting writing this script. (An earlier version of this script wrote all the man pages to plain text files.)
No, it is not normal to have
.txt files in any of those directories.So I guess your earlier script put them there.
But a normal user should not have write access to these directories.
Which seems to suggest that you're playing with a privileged account,
possibly
root.That's a bad idea, avoid using
root casually.Simplify
You can simplify
[[ $n = 'b' || $n = 'B' ]] using pattern matching: [[ $n == [bB] ]].Strangeness
You don't need the
-1 here.menu=( $(ls -1 ${dir}) )When inside
$(...), ls does not columnize its output.In this code, I don't see why you need
basename:echo "$(( i++ ))) $(basename $m)"It seems the value of
$m will always be a simple filename without a path part.Code Snippets
dirs=('' /bin /sbin /usr/bin) # fill the restfor ((index = 1; index < ${#dirs[@]}; index++)); do
echo "$index) ${dirs[$index]}"
donemenu=( $(ls -1 ${dir}) )echo "$(( i++ ))) $(basename $m)"Context
StackExchange Code Review Q#141494, answer score: 2
Revisions (0)
No revisions yet.