Eu não consegui reproduzir seu problema com bash 4.3 e 4.4, portanto, aqui está uma resposta genérica.
Seu problema é acionado pelo ! em PIDS+=($!) , ! sendo o início da substituição do histórico (que é ativado por padrão com um shell interativo).
Desabilite a substituição do histórico com set +H ou cite o ! (não desejável aqui por causa do $ precedente) ou adicione um espaço após ! . O manual do bash lê:
!Start a history substitution, except when followed by a blank, newline, carriage return,=or((when the extglob shell option is enabled using the shopt builtin)
Sua linha de comando se tornaria:
PIDS=()
while read name; do
(cd "$name"; npm install) &
echo started install
PIDS+=( $! )
done < <(\ls)
wait "${PIDS[@]}"
Notas:
- Você não está limitado a uma linha de código aqui
- Eu adicionei aspas adequadas às variáveis
- Você pode esperar vários PIDs de uma só vez; Eu consertei isso