"$ {CM}" não usará caracteres em branco como separadores. Então o bash acha que a string inteira é o nome do seu programa.
Com o $ {CM} bash, pense que "são parte do argumento.
Você pode usar < < eval "$ {CM}" > > mas você pode ter efeitos colaterais com caracteres especiais sem escape nos nomes dos arquivos.
Então é melhor o seguinte:
Isso funciona?
#!/bin bash
for in_file in "$PWD"/*/*/*.txt; do
out_file="$in_file/in/out"
CM="/usr/local/bin/command -in \"$in_file\" -out \"$out_file\""
echo "${CM}"
/usr/local/bin/command -in "$in_file" -out "$out_file"
done
Em vez de repetir seus comandos, use "set -x" para depurar seu script:
#!/bin bash
set -x
for in_file in "$PWD"/*/*/*.txt; do
out_file="$in_file/in/out"
/usr/local/bin/command -in "$in_file" -out "$out_file"
done
ou isto:
#!/bin bash
for in_file in "$PWD"/*/*/*.txt; do
out_file="$in_file/in/out"
set -x
/usr/local/bin/command -in "$in_file" -out "$out_file"
set +x
done