Você deve usar variáveis em minúsculas (é a melhor prática).
Então, usarei o nome do arquivo e a extensão em vez do FILENAME e EXTENSION
Como você diz que "o nome do arquivo é lido de um arquivo", assumirei que o script é:
read -r filename <file.txt
extension=World.txt
E que você deseja concatenar as variáveis $ filename e $ extension com um sublinhado _
.
Os exemplos que você fornece (exceto: no double \) funcionam corretamente aqui:
name=${filename}_$extension
name=${filename}'_'$extension
name=$filename\_$extension
Como alguns outros:
name="${filename}"'_'"${extension}"
name="$filename"'_'"$extension"
name="${filename}_${extension}"
Portanto, seu problema não é como as variáveis são unidas, mas com o conteúdo dos vars. Parece razoável pensar que isso:
read -r filename <file.txt
lerá um retorno de carro à direita \r
se estiver lendo um arquivo do Windows.
Uma solução simples (para ksh, bash, zsh) é remover todos os caracteres de controle da variável de leitura:
filename=${filename//[[:cntrl:]]/}
Isso pode ser simulado com um valor que possui um retorno de carro:
$ 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
Ou, substituindo o valor de filename
:
$ filename="${filename//[[:cntrl:]]/}"
$ echo "start<$filename>end"
start<Hello>end
Conclusão.
Então, é isso:
name="${filename//[[:cntrl:]]/}_${extension//[[:cntrl:]]/}"
Obterá o valor correto para, name
mesmo que os outros vars contenham caracteres de controle.