bash loop with the variable name inside file name [duplicate]

In this particular example, it makes no difference. However, the {} in ${} are useful if you want to expand the variable foo in the string

"${foo}bar"

since "$foobar" would instead expand the variable identified by foobar.

Curly braces are also unconditionally required when:

  • expanding array elements, as in ${array[42]}
  • using parameter expansion operations, as in ${filename%.*} (remove extension)
  • expanding positional parameters beyond 9: "$8 $9 ${10} ${11}"

Doing this everywhere, instead of just in potentially ambiguous cases, can be considered good programming practice. This is both for consistency and to avoid surprises like $foo_$bar.jpg, where it's not visually obvious that the underscore becomes part of the variable name.


Variables are declared and assigned without $ and without {}. You have to use

var=10

to assign. In order to read from the variable (in other words, 'expand' the variable), you must use $.

$var      # use the variable
${var}    # same as above
${var}bar # expand var, and append "bar" too
$varbar   # same as ${varbar}, i.e expand a variable called varbar, if it exists.

This has confused me sometimes - in other languages we refer to the variable in the same way, regardless of whether it's on the left or right of an assignment. But shell-scripting is different, $var=10 doesn't do what you might think it does!


You use {} for grouping. The braces are required to dereference array elements. Example:

dir=(*)           # store the contents of the directory into an array
echo "${dir[0]}"  # get the first entry.
echo "$dir[0]"    # incorrect

You are also able to do some text manipulation inside the braces:

STRING="./folder/subfolder/file.txt"
echo ${STRING} ${STRING%/*/*}

Result:

./folder/subfolder/file.txt ./folder

or

STRING="This is a string"
echo ${STRING// /_}

Result:

This_is_a_string

You are right in "regular variables" are not needed... But it is more helpful for the debugging and to read a script.


Curly braces are always needed for accessing array elements and carrying out brace expansion.

It's good to be not over-cautious and use {} for shell variable expansion even when there is no scope for ambiguity.

For example:

dir=log
prog=foo
path=/var/${dir}/${prog}      # excessive use of {}, not needed since / can't be a part of a shell variable name
logfile=${path}/${prog}.log   # same as above, . can't be a part of a shell variable name
path_copy=${path}             # {} is totally unnecessary
archive=${logfile}_arch       # {} is needed since _ can be a part of shell variable name

So, it is better to write the three lines as:

path=/var/$dir/$prog
logfile=$path/$prog.log
path_copy=$path

which is definitely more readable.

Since a variable name can't start with a digit, shell doesn't need {} around numbered variables (like $1, $2 etc.) unless such expansion is followed by a digit. That's too subtle and it does make to explicitly use {} in such contexts:

set app      # set $1 to app
fruit=$1le   # sets fruit to apple, but confusing
fruit=${1}le # sets fruit to apple, makes the intention clear

See:

  • Allowed characters in Linux environment variable names