foo não sabe qual arquivo ler, ele (presumivelmente) apenas lê seu fluxo de entrada padrão. Esse fluxo de dados é conectado pelo shell ao fluxo de saída padrão do comando cat . Esse "encanamento administrativo" é feito pelo shell quando ele inicia os dois processos (eles seriam executados simultaneamente).
No exemplo da pergunta, é cat que abrirá o arquivo para leitura, lerá e passará os dados em sua saída padrão.
Você também pode perguntar "Como o cat sabe onde gravar o resultado?" A resposta é que ele grava em seu fluxo de saída padrão, conectado pelo shell ao fluxo de entrada padrão do comando foo . Da mesma forma, o fluxo de saída padrão do comando foo é conectado ao terminal pelo shell, pois não há mais canalizações ou redirecionamentos para esse comando.
O canal que você mostra,
cat someFile | foo
é funcionalmente idêntico a
foo <somefile
Aqui eu deletei cat , já que não é realmente necessário. O shell conectará o fluxo de entrada padrão de foo ao arquivo fornecido, para que o efeito seja o mesmo ( foo seria capaz de ler o conteúdo de somefile de seu fluxo de entrada padrão).
Neste último comando, foo ainda não sabe que lê dados provenientes de um arquivo chamado somefile . Ele também não sabe que não está mais lendo a saída de cat . Ele apenas lê seu fluxo de entrada padrão como antes.
Agora é o shell que abrirá o arquivo somefile para leitura, mas o shell não lerá nada do arquivo, apenas conecte o fluxo de entrada padrão com o arquivo aberto para foo ler. / p>
Note que não sabemos o que o comando foo faz, se realmente qualquer coisa com seu fluxo de entrada padrão, ou se espera que um nome de arquivo seja lido em sua linha de comando. Esse tipo de informação estaria disponível no manual do programa foo .
No caso em que foo na verdade precisa que seja instruído a ler um arquivo específico, dando a ele um nome de caminho na linha de comando, você pode usar
foo somefile
Agora, foo seria responsável pela abertura e leitura do arquivo.
Se o arquivo tiver que ser processado de alguma forma (supondo que " cat " seja um processo mais complicado que realmente modifique os dados lidos de somefile ):
cat somefile >newfile
foo newfile
rm newfile
Ou seja, processe o arquivo e salve o resultado em um novo arquivo temporário e, em seguida, passe o nome do arquivo temporário para foo . Em seguida, remova o arquivo temporário.
Ou com um shell que entende substituições de processo (como bash ):
foo <( cat somefile )
Aqui, o shell organizaria para que a saída de cat somefile fosse gravada em um arquivo temporário (ou pipe nomeado, não importa realmente) e o nome do caminho desses dados seria inserido no lugar da substituição do processo %código%. <( ... ) abriria isso como seu arquivo para ler.
Neste exemplo final, foo abriria o arquivo original e o leria enquanto cat abriria qualquer nome de caminho que o shell lhe fornecesse (onde a saída de foo fosse encontrada) e fosse lida a partir dele.