Reindirizza l'output di tutti i comandi su file, non solo per ultimo


11

Voglio aggiungere un'intestazione a un file con eco, quindi utilizzare un comando per creare il resto del file. Questo significa che userò due comandi separati.

Come posso scrivere l'output di entrambi i comandi in un file con reindirizzamento?

ho provato

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

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

Questo reindirizza solo l'output dal comando cut.

Il seguente comando funziona, ma sembra goffo:

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

Qual è il modo intelligente di risolvere il mio problema?

Risposte:


11

Il problema qui non è un problema con il reindirizzamento di Linux; piuttosto, è un fraintendimento fondamentale di come funziona la pipeline. Il reindirizzamento qui non funziona perché in realtà solo il taglio sta stampando su stdout. stdout per il comando echo è stato reindirizzato allo stdin di cut (che non viene utilizzato in questo caso poiché viene specificato un file).

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

è quello che volete, e non poco elegante a tutti (ho sostituito il vostro ;con &&in modo che il comando di taglio verrà eseguito solo se l'intestazione è scritto con successo, in questo modo non verrà eseguito se non si dispone delle autorizzazioni per creare o scrivere output_file ).

Puoi anche fare tutto in una subshell, ad es.

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

ma non vi è alcun vantaggio reale nel fare questo e con esempi più complessi può causare problemi se non si ha familiarità con la definizione della subshell.

Se vuoi che il taglio passi da stdin a stdout puoi provare:

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

(Il trattino è una scorciatoia comune per stdin)

Tuttavia, ciò eseguirà anche l'operazione di taglio su stdin (risultante in una riga di intestazione di "intestazione"). È difficile dire se questo è quello che vuoi o no dalla domanda.


13

Quello che cerchi è:

{ echo "header line"; cut -c 1-5 input_file; } > output_file
  • Questa sintassi non ha effetti collaterali poiché i comandi vengono eseguiti nella shell corrente, non in una shell secondaria
  • Esiste una chiara delimitazione dei comandi che vanno al file output_
  • Ridimensiona bene poiché puoi riscriverlo in questo modo:

{
  echo "header line"
  cut -c 1-5 input_file
  ... # insert new commands here
} > output_file

Se si desidera che l'output dell'errore vada nello stesso file, è possibile modificare l'ultima riga in questo modo:

} > output_file 2>&1

Grazie a Olivier Dulac per aver ricordato quel suggerimento.

Se vuoi che alcuni output all'interno del blocco vadano sullo schermo, puoi usare quella sintassi:

{
  echo "header line"
  echo "this line doesn't go to output_file" > /dev/tty
  cut -c 1-5 input_file
} > output_file

+1: è più chiaro e identifica chiaramente ciò che viene reindirizzato dove. Per reindirizzare tutto (incluso msg di errore): { .... } > some_file 2>&1(sarà "clobber" un_file di non clobber, ma di aggiunta ad esso, invece, basta cambiare il. >In una >>: { ... } >> some_file 2>&1)
Olivier Dulac

4

Solo per completare le risposte c'è exec.

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

+1: negli script è molto comune usarlo (meno nella riga di comando, poiché le cose iniziano a diventare confuse ^^)
Olivier Dulac

Qualcuno potrebbe elaborare questa soluzione? Posso vedere cosa sta facendo, ma non capisco "exec" in questo contesto. Inoltre, sembra che devi disattivare di nuovo se il resto dello script ha bisogno di un normale stdout.
Joe,

1
quando si utilizza exec in uno script senza un comando, è possibile eseguire il reindirizzamento I / O su exec che ha effetto sulla shell corrente e su tutti i figli futuri.
Hildred

Grazie. Non l'ho mai visto prima. Penso che sarà molto utile.
Joe,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.