21

I'm trying to do a simple for loop in a UNIX script (bash).

Here's my script:

for i in {1..3}
do
   echo "Welcome $i times"
done

I was expecting this for output ...

Welcome 1 times
Welcome 2 times
Welcome 3 times

... but I get this ...

Welcome {1..3} times

What am I doing wrong?

5 Answers5

19

You didn't mention how you were executing your script and that can make a difference. Suppose we have a script:

$ cat welcome.sh
for i in {1..3}
do
   echo "Welcome $i times"
done
echo "\n"

Observe the following three invocations of welcome.sh from a bash shell:

$ ps -p $$
  PID TTY          TIME CMD
11509 pts/25   00:00:00 bash
$ source welcome.sh
Welcome 1 times
Welcome 2 times
Welcome 3 times

$ bash welcome.sh
Welcome 1 times
Welcome 2 times
Welcome 3 times

$ sh welcome.sh
Welcome {1..3} times

The last one fails because, on my system, sh defaults to dash, not bash. This is true, for example, for any modern Debian/Ubuntu-derived system.

Top-Master
  • 7,611
  • 5
  • 39
  • 71
John1024
  • 109,961
  • 14
  • 137
  • 171
  • See OP's comment. This seems very unlikely to be the right the answer, unless OP ran it with `sh` (definitely not the right answer if he ran `ps -p $$` from inside the script) – Reinstate Monica Please Jan 27 '14 at 00:01
  • 1
    @BroSlow While you might be right, he did not state that he ran `ps -p $$` "from inside the script" and there are strong indications that he didn't. – John1024 Jan 27 '14 at 00:11
  • 3
    This is a good reminder that `bash`, when invoked as "sh", *silently* drops into compatibility mode. – bishop Mar 29 '16 at 13:22
  • @pushpen.paul If you want to invoke a shell script as `./welcome.sh`, it is best practice to add, as the first line of the script, a shebang line such as `#!/bin/bash` that specifies which shell (or other program) you want to have execute the script. If you want to execute as `./welcome.sh`, it is also necessary that the script have the _execute_ bit set: `chmod +x ./welcome.sh`. – John1024 Jul 18 '19 at 18:04
3

Moving my comment to formal answer:

set -o braceexpand

That enables {x..y} style (amongst other kinds of) expansion. If you want it permanently, add it to your .bashrc. If you want it temporarily, you can "bracket" your code:

set -o braceexpand  # enable brace expansion
echo {1..3}         # or whatever your command is
set +o braceexpand  # disable it

Frankly I think the code overhead of that on/off approach isn't worth it, and I always add brace expansion to my .bashrc.

Finally, here's an excellent discussion of brace expansion ins and outs.

bishop
  • 37,830
  • 11
  • 104
  • 139
2

Several things to try:

  • Run your script with bash as a prefix. bash myscript.sh instead of simply myscript.sh. This will guarantee you're running under BASH.
  • Run set -o and see if braceexpansion is set to on. If not, run set -o braceexpand and see if that fixes your problem.

You can test for whether braceexpand is on or off with the -o test.

if [[ -o braceexpand ]]
then
    echo "Brace expand is on"
else
    echo "It is off"
fi

You can use this to test the state of braceexpand, so you can return it to its previous state.

David W.
  • 105,218
  • 39
  • 216
  • 337
0

I had similar problem, I changed the shebang from

#!/bin/sh

to

#!/bin/bash
-2

Your script is not facing any type of error. I have faced the same problem and the simple solution is that you have not given it the permission to execute so you can do so:

chmod +x nameofyourscript.sh

and then run it like this

./nameofyourscript.sh
Eric Aya
  • 69,473
  • 35
  • 181
  • 253