You should use variables in lowercase (it is the best practice).
So, I'll use filename and extension instead of FILENAME and EXTENSION
As you say that “filename is read from a file”, I'll assume that the script is:
read -r filename <file.txt
extension=World.txt
And that you want to concatenate both variables $filename and $extension with an underscore _
.
The examples you provide (except: no double \) do work correctly here:
name=${filename}_$extension
name=${filename}'_'$extension
name=$filename\_$extension
As some other:
name="${filename}"'_'"${extension}"
name="$filename"'_'"$extension"
name="${filename}_${extension}"
So, your problem is not with how the variables are stick together, but with the contents of the vars. It seems reasonable to think that this:
read -r filename <file.txt
will read a trailing carriage return \r
if reading from a windows file.
One simple solution (for ksh,bash,zsh) is to remove all control characters from the read variable:
filename=${filename//[[:cntrl:]]/}
This could be simulated with a value that has a carriage return:
$ filename=$'Hello\r'
$ echo "starting<$filename>end"
>endting<Hello ### note the return to the start of line.
$ echo "starting<${filename//[[:cntrl:]]/}>end"
starting<Hello>end
Or, replacing the value of filename
:
$ filename="${filename//[[:cntrl:]]/}"
$ echo "start<$filename>end"
start<Hello>end
Conclusion.
So this:
name="${filename//[[:cntrl:]]/}_${extension//[[:cntrl:]]/}"
Will get the correct value for name
even if the other vars contain control characters.