Para ler uma lista de nomes de arquivos de stdin, você pode usar xargs . Por exemplo,
cat files.txt | xargs -d'\n' grep -i -- 'foo'
Por padrão, xargs lê itens da entrada padrão, delimitados por espaços em branco. O -d'\n' diz para usar a nova linha como delimitador de argumentos, para que possa manipular nomes de arquivos contendo espaços em branco. (Como Stéphane Chazelas aponta, essa é uma extensão do GNU). No entanto, ele não lidará com nomes de arquivos contendo novas linhas; precisaríamos de uma abordagem um pouco mais complicada para lidar com isso.
FWIW, essa abordagem é um pouco mais rápida que um loop while read , pois o comando read do bash é muito lento - ele lê seus dados caractere por caractere, enquanto xargs lê sua entrada com mais eficiência. Além disso, xargs invoca apenas o comando grep quantas vezes forem necessárias, com cada chamada recebendo vários nomes de arquivos, e isso é mais eficiente do que invocar grep individualmente para cada nome de arquivo.
Consulte a página de manual xargs e a página de informações xargs para mais detalhes.