Redireciona a saída de todos os comandos para o arquivo, não apenas por último

10

Eu quero adicionar um cabeçalho a um arquivo com eco e, em seguida, use um comando para criar o restante do arquivo. Isso significa que vou usar dois comandos separados.

Como escrevo a saída de ambos os comandos para um arquivo com redirecionamento?

Eu tentei

echo "header line" | cut -c 1-5 input_file > output_file

echo "header line"; cut -c 1-5 input_file > output_file

Isso só redireciona a saída do comando cut.

O comando a seguir funciona, mas parece desajeitado:

echo "header line" > output_file; cut -c 1-5 input_file >> output_file

Qual é a maneira inteligente de resolver meu problema?

    
por The Unfun Cat 27.11.2013 / 14:59

3 respostas

11

O problema aqui não é um problema com o redirecionamento do Linux; em vez disso, é um mal-entendido fundamental de como o pipeline funciona. O redirecionamento aqui não está funcionando porque o corte somente está realmente imprimindo no stdout. stdout para o comando echo foi canalizado para o stdin do cut (que não está sendo usado neste caso desde que um arquivo é especificado).

echo "header line" > output_file && cut -c 1-5 input_file >> output_file

é o que você quer, e não é nada deselegante (eu substituí seu ; por && para que o comando cut só seja executado se o cabeçalho for escrito com sucesso; dessa forma ele não será executado se você não o fizer) t tem permissões para criar ou gravar em output_file).

Você também pode fazer tudo em um subshell, por exemplo.

(echo "header line"; cut -c 1-5 input_file) > output_file

mas não há nenhum benefício real em fazer isso e, com exemplos mais complexos, pode causar problemas se você não estiver familiarizado com o escopo da sub-rede.

Se você quiser que o corte passe stdin para stdout, tente:

echo "header line" | cut -c 1-5 - input_file

(O traço é um atalho comum para stdin)

No entanto, isso também executará a operação de corte no stdin (resultando em uma linha de cabeçalho de "cabeçalho"). É difícil dizer se é isso que você quer ou não da pergunta.

    
por 27.11.2013 / 15:05
13

O que você procura é:

{ echo "header line"; cut -c 1-5 input_file; } > output_file
  • Esta sintaxe não tem efeitos colaterais, pois os comandos são executados no shell atual, não em um subshell
  • Há uma delimitação clara dos comandos que vão para o output_file
  • Ele é dimensionado como você pode reescrevê-lo dessa maneira:
{
  echo "header line"
  cut -c 1-5 input_file
  ... # insert new commands here
} > output_file

Se você quiser que a saída de erro vá para o mesmo arquivo, você pode modificar a última linha dessa maneira:

} > output_file 2>&1

Obrigado a Olivier Dulac por lembrar essa dica.

Se você quiser que alguma saída dentro do bloco vá para a sua tela, você pode usar essa sintaxe:

{
  echo "header line"
  echo "this line doesn't go to output_file" > /dev/tty
  cut -c 1-5 input_file
} > output_file
    
por 27.11.2013 / 15:09
4

Apenas para completar as respostas, há exec.

exec > output_file
echo "header line"
cut -c 1-5 input_file
    
por 27.11.2013 / 15:46