Você entendeu mal a sintaxe. Primeiro, o redirecionamento de entrada tem o símbolo < na frente do arquivo, não na parte de trás. A ordem das operações não é importante. Então, a sintaxe é:
< inputfile command options > outputfile
ou
command options < inputfile > outputfile
(ou outras permutações).
Então, você também tem $ extra. O que você realmente precisa fazer é
$program $options <$inputfile >$outputfile
Você pode substituir ${program} e ${options} por $1 e $2 .
Neste formulário, você pode fazer
#!/bin/bash
<names.txt $1 $2 >test.out
E chame-o como ./execute cat -n ou mesmo ./execute cat '-n -s' se você quiser mais de uma opção. Nesse formulário, você pode ter várias opções, mas precisa colocá-las entre aspas (porque $2 ) não é citado, os espaços expandem o parâmetro de volta para várias palavras.
Outra (melhor) maneira de fazer isso seria usar
#!/bin/bash
<names.txt "$@" >test.out
Agora, você pode passar um número arbitrário de parâmetros para o script, e você pode até ter strings entre aspas nos argumentos e elas permanecem juntas após a propagação no script. Agora isso funciona: ./execute cat -n - "bla bla.txt" (o formulário anterior dividiria o nome do arquivo em duas partes).