man bash
diz:
The order of expansions is: brace expansion; tilde expansion, parameter and variable expansion, arithmetic expansion, and command substitution (done in a left-to-right fashion); word splitting; and pathname expansion [...]
After these expansions are performed, quote characters present in the original word are removed unless they have been quoted themselves (quote removal).
Assim, apenas as citações da palavra original são removidas. Mas essas citações só aparecem após a expansão e não serão removidas.
No caso dado, você pode deixá-los de lado, já que seus nomes de arquivos não precisam de nenhuma citação, mas você terá problemas com nomes de arquivos com espaços em branco ou outros caracteres especiais. E nem citações nem contrabarras o ajudarão, pois não são consideradas citações nesse estágio do processamento.
Editar para atender à solicitação "uma etapa":
Mas e se você tiver vários arquivos com espaços em branco como foo file foo
e bar file bar
e quiser cat
alguns deles?
Sua linha de comando seria lida
cat "foo file foo" "bar file bar"
mas se houver mais, você vai querer fazer o script.
echo -n cat; for name in foo bar; do echo -n \ \"$name file $name\"; done
Produzirá exatamente a linha que você inseriria, mas
$(echo -n cat; for name in foo bar; do echo -n \ \"$name file $name\"; done)
falhará pelo motivo explicado acima. Colocar tudo entre aspas duplas (como ajudou no seu caso gimp
) também não funcionará, porque o novo comando precisa ser separado em palavras, mas não entre aspas.
Então, o que fazer para que as cotações funcionem como se fossem inseridas diretamente na linha de comando? Passe sua string como comando para o shell:
bash -c "$(echo -n cat; for name in foo bar; do echo -n \ \"$name file $name\"; done)"
Essa deve ser a abordagem mais geral para um one-liner executando um comando gerado.