O problema é que as aspas simples não são especiais para tcl , portanto, você está realmente executando o comando grep com o argumento '\.foo' , incluindo as aspas que normalmente seriam removidas pelo shell.
Isso faz com que o grep não corresponda, portanto, ele sai com um código de erro diferente de zero e, portanto, o comando exec transmite o erro.
A resposta imediata é usar tcl aspas duplas ( grep -E "\.foo" ) ou não aspas ( grep -E \.foo ) ou aspas ( grep -E {\.foo} ). Mas uma alternativa é não recorrer a comandos de shell. O equivalente em tcl pode ser:
set fullfiles [glob *.foo]
foreach f $fullfiles { lappend files [string trimright $f .foo] }