O problema é que você não está citando a variável $ENV . Conforme explicado em man bash :
Enclosing characters in double quotes preserves the literal value of all characters within the quotes, with the exception of $, ', \, and, when history expansion is enabled, !. The characters $ and ' retain their special meaning within double quotes. The backslash retains its special meaning only when followed by one of the following characters: $, ', ", \, or .
Portanto, incluir uma sequência como \n nas aspas duplas preserva seu significado. É por isso que, quando não é cotado, \n é apenas um% normaln:
$ printf \n
n$
Enquanto, quando citado:
$ printf "\n"
$
Uma variável sem nome no bash invoca o operador split + glob. Isso significa que a variável é dividida em espaço em branco (ou qualquer que seja a variável especial $IFS definida) e cada palavra resultante é usada como glob (expandirá para corresponder a qualquer nome de arquivo correspondente). Seu problema é com a parte "dividida" disso.
Para ilustrar, vamos pegar uma variável multilinha mais simples:
$ var=$(printf "foo\nbar\n")
Agora, usando o recurso de depuração set -x do shell, você pode ver exatamente o que está acontecendo:
$ echo $var
+ echo foo bar
foo bar
$ echo "$var"
+ echo 'foo
bar'
foo
bar
Como você pode ver acima, echo $var (sem aspas) apresenta $var para dividir + glob. Isso resulta em duas sequências separadas, foo e bar . A nova linha foi comida pela divisão split + glob. Quando a variável foi citada, não foi submetida a split + glob, a nova linha foi mantida e, por ser citada, também é interpretada corretamente e impressa.
O próximo problema é que printf não é como echo . Ele não imprime apenas qualquer coisa que você der, ele espera uma string de formato. Por exemplo, printf "color:%s" "green" imprimirá color:green porque o %s será substituído por green .
Ele também ignora qualquer entrada que não possa caber na string de formato que foi fornecida. Portanto, se você executar printf foo bar , printf tratará foo como sua string de formato e bar como a variável que deve formatar com ela. Como não há %s ou equivalente a ser substituído por bar , bar é ignorado e foo é impresso sozinho:
$ printf $var
+ printf foo bar
foo
Foi o que aconteceu quando você executou printf $ENV_BEFORE . Como a variável não foi citada, a divisão glob substituiu efetivamente as novas linhas por espaços, e printf apenas imprimiu a primeira "palavra" que viu.
Para fazer isso corretamente, use strings de formato e sempre cite suas variáveis:
printf '%s\n' "$ENV_BEFORE"