Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I want to add a header to a file with echo, then use a command to create the rest of the file. This means I'll be using two separate commands.

How do I write the output from both commands to a file with redirection?

I've tried

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

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

This only redirects the output from the cut command.

The following command works, but feels clumsy:

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

What is the clever way of solving my problem?

share|improve this question
add comment

3 Answers

up vote 10 down vote accepted

The problem here isn't an issue with Linux redirection; rather, it's a fundamental misunderstanding of how the pipeline works. Redirection here isn't working because only cut is actually printing to stdout. stdout for the echo command has been piped to cut's stdin (which isn't being used in this case since a file is specified).

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

is what you want, and not inelegant at all (I replaced your ; with && so that the cut command will only execute if the header is successfully written; this way it won't execute if you don't have permissions to create or write to output_file).

You could also do it all in a subshell, eg.

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

but there's no real benefit to doing this and with more complex examples it can cause issues if you're not familiar with how the subshell is scoped.

If you want cut to pass stdin through to stdout you could try:

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

(The dash is a common shortcut for stdin)

However, this will also perform the cut operation on stdin (resulting in a header line of "header"). It's hard to tell if this is what you want or not from the question.

share|improve this answer
add comment

What you look for is:

{ echo "header line"; cut -c 1-5 input_file; } > output_file
  • This syntax has no side effects as the commands are executed in the current shell, not a subshell
  • There is a clear delimitation of the commands that go to the output_file
  • It scales well as you can rewrite it that way:

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

Should you want the error output to go to the same file, you can modify the last line that way:

} > output_file 2>&1

Thanks to Olivier Dulac for reminding that tip.

Should you want for some output inside the block to go to your screen, you can use that syntax:

{
  echo "header line"
  echo "this line doesn't go to output_file" > /dev/tty
  cut -c 1-5 input_file
} > output_file
share|improve this answer
    
+1 : it's clearer and clearly identifies what is redirected where. To redirect everything (including error msg) : { .... } > some_file 2>&1 (will "clobber" some_file. to not clobber, but append to it instead, just change the > into a >>: { ... } >> some_file 2>&1) –  Olivier Dulac Nov 27 '13 at 17:35
add comment

Just to round out the answers there is exec.

exec > output_file
echo "header line"
cut -c 1-5 input_file
share|improve this answer
    
+1 : in scripts it's very common to use this (less so on the command line, as things start to get confusing ^^) –  Olivier Dulac Nov 27 '13 at 17:38
    
Could someone elaborate on this solution? I can see what it's doing, but I don't understand 'exec' in this context. Also, it looks like something you have to turn off again if the rest of your script needs normal stdout. –  Joe Nov 30 '13 at 8:53
1  
when you use exec in a script without a command, you can do I/O redirection on the exec which affects the current shell and all future children. –  hildred Nov 30 '13 at 8:57
    
Thanks. I have not seen that before. I think it will be very useful. –  Joe Dec 3 '13 at 21:20
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.