Quando você executa
ls|more
o shell analisa essa linha e entende que os três tokens são o comando ls seguido por um pipe, seguido pelo comando more . Quando você executa
$x
o shell expande essa variável, mas não analisa o resultado, pelo menos não da mesma maneira. Ele dividirá o conteúdo da variável no espaço em branco, considerará a primeira seqüência de caracteres como um nome de comando e as seguintes sequências de caracteres como argumentos. Por isso, vai entender ls|more como sendo o comando ls|more e ls | more como o comando ls seguido pelos argumentos | e more , que ls considera nomes de arquivos.
Para fazer com que o shell repare o conteúdo dessa variável, use eval , desta forma:
eval "$x"