Vous devez utiliser des variables en minuscule (c'est la meilleure pratique).
Donc, je vais utiliser le nom de fichier et l'extension au lieu de FILENAME et EXTENSION
Comme vous dites que "nom de fichier est lu à partir d'un fichier", je suppose que le script est:
read -r filename <file.txt
extension=World.txt
Et que vous souhaitiez concaténer les variables $ filename et $ extension avec un trait de soulignement _
.
Les exemples que vous fournissez (sauf: pas de double \) fonctionnent correctement ici:
name=${filename}_$extension
name=${filename}'_'$extension
name=$filename\_$extension
Comme un autre:
name="${filename}"'_'"${extension}"
name="$filename"'_'"$extension"
name="${filename}_${extension}"
Votre problème ne réside donc pas dans la façon dont les variables sont collées ensemble, mais dans le contenu des variables. Il semble raisonnable de penser que ceci:
read -r filename <file.txt
lira un retour chariot final \r
s'il lit un fichier Windows.
Une solution simple (pour ksh, bash, zsh) consiste à supprimer tous les caractères de contrôle de la variable en lecture:
filename=${filename//[[:cntrl:]]/}
Cela pourrait être simulé avec une valeur qui a un retour chariot:
$ 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, en remplaçant la valeur de filename
:
$ filename="${filename//[[:cntrl:]]/}"
$ echo "start<$filename>end"
start<Hello>end
Conclusion.
Donc ça:
name="${filename//[[:cntrl:]]/}_${extension//[[:cntrl:]]/}"
Obtiendra la valeur correcte name
même si les autres vars contiennent des caractères de contrôle.