O problema é que as atribuições de parâmetros opcionais são reconhecidas antes da expansão do parâmetro, então a linha
$X
é reconhecido como um comando sem atribuições anteriores. A primeira palavra do resultado da expansão é assumida como sendo o nome do comando, portanto, o shell tenta executar Y=10
.
Como geralmente é o caso, você não deve tentar armazenar código em uma variável, mas sim em uma função.
X () {
Y=10 echo foo
}