Creating script to cp directory multiple times
Solution 1:
{2..5}
is brace expansion. Brace expansion is not standardized by POSIX. Some, but not all, of the widely used Bourne-style shells support it.
The shell you interact with in a terminal on Ubuntu is bash
, unless you're deliberately using a different one. bash
supports brace expansion. But the shebang on your script is for sh
, which on Ubuntu is a symlink to dash
. dash
does not support brace expansion.
So you can either:
- Make your script a
bash
script (or a script for some other shell that supports brace expansion, such aszsh
orksh
). - Replace brace expansion in your script with something that works in
dash
.
If you want to make your script a bash
script, replace
#!/bin/sh
with:
#!/bin/bash
Then when run like ./scriptname
it will be run in bash
. If you're running your script by writing sh scriptname
then you must use bash scriptname
instead.
If you want to eliminate brace expansion, there are a few alternatives. I suggest seq
with command substitution, which is probably the most common alternative to brace expansion, is easy to write, and is likely to be understood by other human readers.
In place of {2..5}
, you can write $(seq 2 5)
. Since it is not quoted--that is, since it is $(
)
and not "$(
)"
--field splitting (which in bash
is called word splitting) is performed on the result. So long as you have not set the IFS
shell variable, which controls field splitting, to a value that contains any digit or that does not contain a newline, this will do what you want.
(Globbing--also called filename expansion, also called pathname expansion--is also performed on the result of unquoted command substitution, but the output of seq
will not contain the globbing characters ?
, *
, or [
, so that has no effect in this case.)
Note that seq
is not standardized by POSIX. This will work on just about any GNU/Linux system and some other Unix-like operating systems, but some Unix-like OSes don't have seq
installed by default (they usually have jot
instead) so it is not guaranteed to work on all Unix-like operating systems.
Solution 2:
When you run the script in your terminal, the shell that you are using is most likely Bash. Bash supports brace expansion, so {2..5}
gets expanded to the sequence 2 3 4 5
and your script works as you expect it to work.
When you add the same scipt to a file, however, it does not work. This is due to the shebang that you are using (#!/bin/sh
), which tells your script to run in the sh shell, which is POSIX-compliant and does not support braces expansion.
So you have two options:
- Change the shebang to
#!/bin/bash
or another shell that supports brace expansion.
or
- Use
#!/bin/sh
and replace{2..5}
by$(seq 2 5)
.
Also take a look at this interesting Stack Overflow question about the differences between sh and Bash.