Janko
Janko

Reputation: 9305

Variable in curly braces not working

I have a directory with country folders, where there might be folders that have doubled name:

 en_en es_es fr_fr de_de

And I wrote a script to remove the duplication:

 for code in en de es fr it nl pt tr; do
   if [[ -d $code_$code ]]; then
     mv "${code}_${code}" "${code}"
   fi
 end

But it doesn't work – the code under if never gets executed (I tried putting an echo there as well). However, the following works:

 if [[ -d es_es ]]; then
   echo "foo"
 end

I'm using (log)bash 3.2.

Upvotes: 1

Views: 635

Answers (2)

fedorqui
fedorqui

Reputation: 289495

Because $code_$code is looking for code_ + code, while you want to check code+ _ + code. To do so, use braces: ${code}_${code}.

for code in en de es fr it nl pt tr; do
   if [[ -d "${code}_${code}" ]]; then # <---- here (note also it is good to quote)
     mv "${code}_${code}" "${code}"
   fi
end

This happens because _ can be present in the name of a variable, hence we use braces to define exactly what is the name when calling them.

See another example:

$ this=3
$ that=4
$ echo $this_$that
4
$ echo ${this}_${that}
3_4
$ this_=5
$ echo $this_$that
54

Upvotes: 9

Tiago Lopo
Tiago Lopo

Reputation: 7959

The problem is $code_$code. The underscore is a valid character for identifiers, therefore bash is looking for variable $code_.

It can be fixed by using \_ or "${code}_${code}", latter preferred.

Example:

[root@TIAGO-TEST2 tmp]# for code in en de es fr it nl pt tr; do echo $code_$code; done
en
de
es
fr
it
nl
pt
tr

Using \_ :

[root@TIAGO-TEST2 tmp]# for code in en de es fr it nl pt tr; do echo $code\_$code; done
en_en
de_de
es_es
fr_fr
it_it
nl_nl
pt_pt
tr_tr

Using ${code}_{code} :

[root@TIAGO-TEST2 tmp]# for code in en de es fr it nl pt tr; do echo ${code}_${code}; done
en_en
de_de
es_es
fr_fr
it_it
nl_nl
pt_pt
tr_tr

Upvotes: 2

Related Questions