7

I am in the process of creating a bash script that will list the files (in this case apache sites-available). Listing the files is easy by my ultimate goal would be to take each of those files into an array, display them to the user and allow the user to select which "file" to process, in this case it would be to enable the site.

I haven't gotten very far, I know I need to set the ls as an array and then loop the action:

array=$(ls)
for sites in $array(2)
do
echo "$sites"
done

I know that I need to index each of the files in the directory and then allow the user to type the number to enable. So it would look like this:

(1) newdomain.com
(2) newdomain2.com

Which site would you like to enable (i.e 1)?

Hopefully that makes sense?

3 Answers 3

7

You could save yourself a lot of reimplementation by using the built-in select feature.

The select construct allows the easy generation of menus. It has almost the same syntax as the for command:

select name [in words ...]; do commands; done

The list of words following in is expanded, generating a list of items. The set of expanded words is printed on the standard error output stream, each preceded by a number. If the in words is omitted, the positional parameters are printed, as if in "$@" had been specified. The PS3 prompt is then displayed and a line is read from the standard input. If the line consists of a number corresponding to one of the displayed words, then the value of name is set to that word. If the line is empty, the words and prompt are displayed again. If EOF is read, the select command completes. Any other value read causes name to be set to null. The line read is saved in the variable REPLY.

Sign up to request clarification or add additional context in comments.

Comments

6

That's not how you use ls.

array=(*)

6 Comments

That works in the current directory, however the script can be invoked from anywhere so I would have to define the full path (i.e /etc/apache2/sites-available/).
This differs from what you would have to do with ls how?
Clarifying: you need a set of parentheses to indicate an array assignment, so at minimum you would need to say array=($(ls whatever)). Otherwise you're getting a long string.
Here's a good essay spelling out why parsing ls is a bad idea.
@jason.dot.h, array=( /etc/apache2/sites-available/* ) works fine. If you want to strip the directory names on expansion, that's easily done: Refer to "${array[@]##*/}" and you get only the filenames, without all the bugs that come from using ls programatically.
|
-1

some hint to get you started :

APACHE_CONF=/etc/apache2
SITES_TO_ENABLE="site1.org | site2.com"
LIST_AVAILABLE=$(ls $APACHE_CONF/sites-available)
LIST_ENABLED=$(ls $APACHE_CONF/sites-enabled)

for site in $(echo $SITES_TO_ENABLE | sed -e "s/|//g")
do
    FOUND=$(echo $LIST_AVAILABLE | sed -e "s/ /\n/g" | egrep $site)
    [[ ! -z $FOUND ]] && echo "Checking availability of $site: Ok"
    [[ -z $FOUND ]] && echo "Checking availability of $site: Nok, site \"$site\" required for production has not been found or is not defined" && exit 1
done

You can combine this approach with select of course.

1 Comment

This works only until a file in one of the directories contains a space in its name, or a wildcard character, or anything else unprintable or found inside IFS. See also mywiki.wooledge.org/ParsingLs

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.