$@ deve ser usado apenas no formulário "$@" , sozinho em uma palavra. Quando "stuff$@" é expandido, isso resulta em uma lista que consiste no primeiro parâmetro posicional com stuff prefixado e, em seguida, os outros parâmetros posicionais. Por exemplo, se os parâmetros posicionais forem foo e bar , você obterá duas palavras: stufffoo e bar . Esse é um dos seus problemas.
Outro problema é que, com sh -c , o primeiro argumento não-opcional se torna o nome do script que está disponível como $0 . Argumentos subseqüentes de não-opção se tornam parâmetros posicionais. Por isso, sh -c 'echo "$@"' foo bar qux imprime bar qux - foo está em $0 , bar em $1 e qux em $2 .
Para passar os argumentos da função para o script, use $@ no script (não, como você fez, na função - "stuff$@" é expandido no shell que executa a função, devido às aspas duplas ). E conta para $0 .
test() { bash -c 'testargs() { echo "$@"; }; testargs "$@"' myscript "$@"; }