I have the following script I use to make webapp conf files (under /etc/nginx/sites-available/).

This is the script:


for domain; do
    cat <<-WEBAPPCONF > /etc/nginx/sites-available/${domain}.conf
        server {
            root var/www/html/${domain};
            server_name ${domain} www.${domain};
            location / {
                index index.php index.html index.htm fastcgi_index;
                try_files $uri $uri =404 $uri/ /index.php?$args;
            location ~ \.php$ {
                fastcgi_pass unix:/var/run/php/php*-fpm.sock;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                include fastcgi_params;
    ln -s /etc/nginx/sites-available/${domain}.conf /etc/nginx/sites-enabled/

systemctl restart nginx.service

Given it has a for loop for a domain variable, I can run it for multiple domains by passing these domains as arguments for domain:

bash ~/nwsm domain_1.tld domain_2.tld

My question

Please assume that for whatever reason I prefer not to use a for loop and work only with one domain each time:

If I'll remove the for domain; do ... done syntax, I assume I wouldn't be able to pass a domain as an argument because there isn't a domain variable to hold it as a value. Hence I ask what is the correct way to change the script so that it would process only one domain argument, without a for loop?

I'm not sure just adding domain at the start of the script is the correct way to do that.


Some weak arguments to why someone would want to even do that (because the for loop works quite fine to be honest):

1) Reducing the amount of lines when aspiring to minimalism.

2) Setting oneself both mentally to work with one domain at a time will reduce the chance for extra typing and typos and will ease validation of what's already written.

3) Using a for loop is redundant in some small environments when you work with a sparse number of domains (<=5 domains).

  • domain=${1?missing domain} could be useful, but you might also want to check [ $# = 1 ] so that extra args are not just ignored. – meuh Jan 14 '18 at 15:08
test -z "$domain" && exit 2


The second line is not an answer to the question. It shall solve / reduce a problem which would not be there if a loop over the positional parameters was used.

If a script is (by mistake) called without positional parameters then nothing happens in case of a loop. But a non-loop script runs in any case, potentially causing harm because the commands differ from what they should look like.

Thus it should at least be checked that the argument exists (better: check that it is a valid value). If the argument has an illegal value or is empty (non-existing) then the script should abort.

The shell builtin exit aborts the current shell. This works both in an interactive shell and in shell scripts. exit can have a non-negative integer as argument (the default is zero). This is the exit code of the aborted shell.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.