Como esse comando é legal? "> Arquivo1 <arquivo2 gato"

61

Supondo que file2já exista, o comando

> file1 < file2 cat

parece estar copiando o conteúdo de file2para file1.

Mas não consigo entender essa estrutura.

Entendo que "Nada" está sendo direcionado para file1(criar ou apagar seu conteúdo). Então o conteúdo de file2está sendo direcionado file1.

Por que é catdepois file2? como saber cat file2se os operandos não estão na ordem correta?

shaqed
fonte
11
Qual "ordem correta"? Você pode fornecer um link para algum recurso / material de aprendizagem onde uma "ordem correta" é descrita?
Lightness Races com Monica
7
Ao fazer perguntas como essa, você deve especificar o shell; diferentes têm casos distintos, especialmente em relação ao redirecionamento.
usar o seguinte comando

Respostas:

117

Antes de o shell executar o catcomando na linha de comando, ele procura por redirecionamentos.

Existem dois redirecionamentos:

  1. >file1 Isso fará com que a saída padrão do comando vá para file1.
  2. <file2 Isso fará com que a entrada padrão do comando venha file2.

O fato de esses redirecionamentos serem colocados em um local instável na linha de comando não importa.

$ cat <file2 >file1

é o mesmo que

$ <file2 cat >file1

que é o mesmo que

$ <file2 >file1 cat

etc.¹

Observe que o catutilitário em todas essas instâncias é executado sem nenhum argumento de linha de comando . Os redirecionamentos não são operandos para o catcomando, são instruções para o shell para configurar redirecionamentos para dentro e fora do comando (conectando sua entrada e saída padrão aos arquivos). O shell configura os redirecionamentos antes de chamar o comando.

A diferença entre cat filee cat <file(ou, se você preferir <file cat) é que, no primeiro caso, o catpróprio utilitário está abrindo o arquivo, que é fornecido como um operando na linha de comando, para leitura, enquanto no segundo caso, o shell irá abra o arquivo e conecte cato fluxo de entrada a ele². No segundo caso, catnotará que não recebeu um operando de arquivo e passará automaticamente para a leitura de sua entrada padrão. Esse é um recurso cate alguns outros utilitários, não algo que todos os utilitários fazem.

cattambém lerá sua entrada padrão se receber o operando -. Novamente, isso é especial apenas para cate para alguns outros utilitários (ou seja, nada que o shell faça). Para usar catem um arquivo no diretório atual cujo nome é - , adicione um caminho ao nome do arquivo, como ./-.

¹ A ordem dos redirecionamentos ainda é importante em algumas circunstâncias; Com cat <file2 >file1, por exemplo, file1não será truncado se file2estiver inacessível (os redirecionamentos são analisados ​​da esquerda para a direita). A colocação relativa da palavra catainda é arbitrária e não influenciará isso.

² Veja também a pergunta " cat dá erro diferente ao abrir arquivo inexistente ".


O fato de o shell configurar os redirecionamentos antes mesmo de executar o comando na linha de comando é o motivo pelo qual essas coisas falham e você acaba com um arquivo de saída vazio:

$ sort file >file

Aqui, o shell truncará (esvaziará) o arquivo fileantes de executar sort filee conectar sorta saída padrão do arquivo. O sortutilitário abrirá filee classificará seu conteúdo (o que não é nada). O resultado (nada) é passado pelo fluxo de saída padrão para file.

O remédio nesse caso específico (para classificar um arquivo "no local") é

$ sort -o file file

ou

$ sort file >file.sorted && mv file.sorted file

que é mais ou menos o que sortfaz ao usar o -oarquivo para especificar o nome do arquivo de saída.


Apenas para fazer backup da declaração de que os redirecionamentos podem preceder o nome real do utilitário na linha de comando:

Um "comando simples" é uma sequência de atribuições e redirecionamentos de variáveis ​​opcionais, em qualquer sequência, opcionalmente seguidos por palavras e redirecionamentos, finalizados por um operador de controle. [ref: POSIX Shell Command Language 2.9.1 Comandos Simples]

E também sobre o redirecionamento não fazer parte dos operandos do utilitário:

O número opcional, o operador de redirecionamento e a palavra não devem aparecer nos argumentos fornecidos ao comando a ser executado (se houver). [ref: Redirecionamento da linguagem de comando do shell POSIX 2.7]

Kusalananda
fonte
14
@Steve A liberdade de mover redirecionamentos pode ser usada para tornar alguns comandos mais claros, como um pipeline com redirecionamento de entrada no início <in foo | bar >outcoloca tudo em ordem lógica. Eu também gosto se echo >&2 Something bad happeneda saída de erro de scripts de shell. Mas >out <in caté ofuscação apenas
2
Como pode sort file >fileser realizado corretamente?
seth10
11
@setht Com sort -o file file.
Kusalananda
6
Ótima resposta. Observe que o pedido é importante. < file1 > file2 catseria melhor do > file2 < file1 catque evitaria file2ser truncado se file1não puder ser aberto.
Stéphane Chazelas
3
Algo a ter em atenção: ao vincular ao POSIX com fragmentos HTML, é melhor especificar a edição exata (como pubs.opengroup.org/onlinepubs/9699919799.2016edition ), pois sabe-se que os fragmentos mudam entre as edições de uma mesma revisão da especificação (muitos links nas respostas deste site, incluindo o meu, agora estão errados, pois os fragmentos apontam para o lugar errado após o lançamento da edição de 2016).
Stéphane Chazelas