LinuxQuestions.org
Share your knowledge at the LQ Wiki.
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Software
User Name
Password
Linux - Software This forum is for Software issues.
Having a problem installing a new program? Want to know which application is best for the job? Post your question in this forum.

Notices



Reply
 
Search this Thread
Old 02-07-2006, 10:39 AM   #1
edwin11
Member
 
Registered: Dec 2005
Distribution: Linux Mint 13 MATE
Posts: 120

Rep: Reputation: 15
Question BASH: How to Redirect Output to File, AND Still Have it on Screen


Hi,

Actually this is quite a straightforward question, but somehow i can't find the answer (maybe i'm searching the wrong places). The places i see all teach me how to redirect to file fullstop.

OK, the question...

I know that to redirect the output of a command to a file, i do this:

Code:
ls -l > filename
But what if i want to log the output to file, AND have it displayed on screen (as it would if it were not redirected) as well? Is it possible to do this?



TIA and Regards,
Edwin
 
Old 02-07-2006, 10:43 AM   #2
homey
Senior Member
 
Registered: Oct 2003
Posts: 3,057

Rep: Reputation: 56
Try this

ls -al | tee file.txt
 
2 members found this post helpful.
Old 02-07-2006, 10:56 AM   #3
edwin11
Member
 
Registered: Dec 2005
Distribution: Linux Mint 13 MATE
Posts: 120

Original Poster
Rep: Reputation: 15
Brilliant... thanks!



Regards,
Edwin
 
Old 02-07-2006, 11:09 AM   #4
homey
Senior Member
 
Registered: Oct 2003
Posts: 3,057

Rep: Reputation: 56
You're welcome!
 
Old 02-07-2006, 11:40 AM   #5
haertig
Senior Member
 
Registered: Nov 2004
Distribution: Debian, Ubuntu, LinuxMint, Slackware, SysrescueCD
Posts: 2,032

Rep: Reputation: 309Reputation: 309Reputation: 309Reputation: 309
If you want to capture error output (stderr) along with normal output (stdout):
Code:
ls -l 2>&1 | tee file.txt
 
Old 02-08-2006, 12:50 AM   #6
edwin11
Member
 
Registered: Dec 2005
Distribution: Linux Mint 13 MATE
Posts: 120

Original Poster
Rep: Reputation: 15
Thanks,

Would the ordering between "| tee file.txt" and "2>&1" matter?

Asking as "ls -l > file.txt 2>&1 file.txt" is different from "ls -l 2>&1 > file.txt".



Regards,
Edwin
 
Old 02-08-2006, 07:02 AM   #7
timmeke
Senior Member
 
Registered: Nov 2005
Location: Belgium
Distribution: Red Hat, Fedora
Posts: 1,515

Rep: Reputation: 61
Actually,
Code:
ls -l 2>&1 | tee file.txt
may not work as you expect it.
It is likely that you won't see the stderr and stdout messages in the order in which they were sent to your terminal, simply because stdout (file descriptor 1) is buffered and stderr (2) is not (or was that the other way around - I keep mixing that up). So you'll see the stderr messages first and then the stdout ones (or vice-versa).

If you want the stderr and stdout messages to appear in the right order, you'll need to use a subshell, like so:
(ls -l 2>&1) > file.txt
or
(ls -l 2>&1) | tee file.txt if you want it to appear on screen and in file.txt
This basically says that it should execute the ls -l command, sending stderr to stdout in a subshell. All output from the subshell then comes from the subshell's stdout, and you can capture it in a file or with "tee".
The subshell will only make sure that the stderr and stdout messages appear in the right order.
 
Old 02-08-2006, 09:14 AM   #8
edwin11
Member
 
Registered: Dec 2005
Distribution: Linux Mint 13 MATE
Posts: 120

Original Poster
Rep: Reputation: 15
i just tried it out, using a simple self-written command.sh shell script which has a number of standard and error output.

Seems like

Code:
$ ./command.sh 2>&1 | tee command.log
works fine (even without the sub-shell). Both the terminal and the log file recorded output in the correct order. Of course, adding the parenthesis does no harm.

However,

Code:
$ ./command.sh | tee command.log 2>&1
(with or without parenthesis) displays all the error output followed by all the normal output, and logs only the normal output.


This behaviour seems to run opposite if i use "> command.log" instead of "| tee command.log".

Code:
$ ./command.sh > command.log 2>&1
logs both the normal and error output in the correct order.

Code:
$ (./command.sh > command.log) 2>&1
logs only the normal output and displays only the error output.

Code:
$ ./command.sh 2>&1 > command.log
also logs only the normal output and displays only the error output.

Code:
$ (./command.sh 2>&1) > command.log
logs both normal and error output in the correct order, and displays nothing.




Regards,
Edwin
 
Old 02-08-2006, 11:30 AM   #9
haertig
Senior Member
 
Registered: Nov 2004
Distribution: Debian, Ubuntu, LinuxMint, Slackware, SysrescueCD
Posts: 2,032

Rep: Reputation: 309Reputation: 309Reputation: 309Reputation: 309
I have to admire you for running all these tests to try to learn. The three pieces I think you're missing in your analysis are "How many commands am I running?", "What order am I redirecting things in?" and "What does | do anyway?"

The first missing piece:
---

For example
Code:
./command.sh >file.txt 2>&1
is only running ONE command, namely "command.sh"

However
Code:
./command.sh 2>&1 | tee file.txt
is running TWO commands, namely "command.sh" and "tee"

When you are running more than one command, you have to remember that EACH command has it's own stdout and stderr. So depending on where you put that little "2>&1" thingy, for example, will determine whether you're redirecting stderr from "command.sh" or from "tee". The same goes for when you're running subshells. The subshell itself is a command so think about whether you're redirecting output from "command.sh" which is running within the subshell, or redirecting output from the subshell itself.

To the second missing piece:
---

Remember "1" = stdout and "2" = stderr. "1" is assumed if you don't provide a number.

Example: ls -l >file.txt is the same as ls -l 1>file.txt

An ampersand can be thought of as meaning: "to the same place as"

Example: ls -l >file.txt 2>&1 means "Send stdout to file.txt and send stderr to the same place as stdout

When we're talking ampersands, "to the same place as" has to also take into account "at this time"

Example
Code:
ls -l >file.txt 2>&1
will send both stdout and stderr to file.txt. Why? Because FIRST stdout was redirected to file.txt and THEN stderr was told to go to the same place as stdout.

On the other hand
Code:
ls -l 2>&1 >file.txt
will send stderr to your screen and stdout to file.txt. Why? Because stderr was redirected to the same place as stdout, but at this time stdout was still pointing to the console. stdout was not redirected to file.txt until AFTER stderr had been redirected. When we are talking AFTER in this example we are talking about placement on the command line. Things specified further to the right are thought of as coming after. So this example does nothing for stderr. stderr is indeed redirected to the same place as stdout, which is the console at the time of the redirection, but stderr was ALREADY pointing there in the first place - resulting in no perceivable change.

To the third missing piece:
---

The pipe symbol "|" can be thought of like a fancy redirection of stdout. It redirects stdout from the first command to the stdin of the second command. So ls -l | tee file.txt says "Take the stdout of ls and send it to the stdin of tee. "tee" is simply a program that takes its stdin and sends it to two places, stdout and also to a file.

The eagle-eyed observer will notice an apparent discrepancy for "|" ...

ls -l 2>&1 | tee file.txt will log BOTH stdout and stderr from ls to file.txt. But at this time, when stderr was redirected to the same place as stdout, stdout had not yet been redirected to tee via the "|". Hmmm ... gotcha! Just one of those things. Never fails - when you try to rationalize your way through something logically ... you run into an exception! This is one of those things were experience tells me "I know it works this way", but when you press me with the "why?" question, I have to hem and haw and say "Because that's the way it is!"

---

Now that you head is spining with this cryptic "explanation", maybe it will start making more sense why you're seeing what you're seeing in your tests.

[edit]Corrected a few of my spelling errors![/edit]

Last edited by haertig; 02-08-2006 at 11:33 AM.
 
1 members found this post helpful.
Old 02-09-2006, 08:40 AM   #10
edwin11
Member
 
Registered: Dec 2005
Distribution: Linux Mint 13 MATE
Posts: 120

Original Poster
Rep: Reputation: 15
Thanks haertig for the explanation! The results of the tests that i ran certainly makes sense now.

As for

Code:
ls -l 2>&1 | tee file.txt
Can we say that:
First, the stderr is redirected to where the stdout goes.
Then we send whatever "comes out" of where stdout normally "comes out", and send it to tee.
And since at that point, both stdout and stderr "comes out" of that place, both are piped to tee, which both displays and sends it to file.
?



Thanks and Regards,
Edwin
 
Old 02-09-2006, 10:25 AM   #11
haertig
Senior Member
 
Registered: Nov 2004
Distribution: Debian, Ubuntu, LinuxMint, Slackware, SysrescueCD
Posts: 2,032

Rep: Reputation: 309Reputation: 309Reputation: 309Reputation: 309
Quote:
Originally Posted by edwin11
Can we say that:
First, the stderr is redirected to where the stdout goes.
Then we send whatever "comes out" of where stdout normally "comes out", and send it to tee.
And since at that point, both stdout and stderr "comes out" of that place, both are piped to tee, which both displays and sends it to file.
Yes, I think we can say this!
 
Old 02-27-2007, 12:31 PM   #12
na5m
Member
 
Registered: Jan 2005
Location: california
Distribution: O.A.M. (Overmonitoring Address Matrix) Release 2.2 with 2120 Patch
Posts: 37

Rep: Reputation: 17
ampersand

Actually, I don't think that the ampersand strictly means "to the same place as". I think that the ampersand is necessary so that "1" isn't interpreted as a file.
The code
Code:
ls 1>1
will redirect stdout to a file named "1"
Whereas
Code:
ls 1>&1
will redirect stdout to stdout.

ADDITION:
Try
Code:
ls 1>&1>&1>&1>&1

Last edited by na5m; 02-27-2007 at 12:39 PM.
 
1 members found this post helpful.
Old 11-22-2010, 09:08 AM   #13
doru
Member
 
Registered: Sep 2008
Distribution: Ubuntu 8.04 LTS Server
Posts: 89

Rep: Reputation: 16
ampersand

Quote:
Originally Posted by na5m View Post
Actually, I don't think that the ampersand strictly means "to the same place as". I think that the ampersand is necessary so that "1" isn't interpreted as a file.
The code
Code:
ls 1>1
will redirect stdout to a file named "1"
Whereas
Code:
ls 1>&1
will redirect stdout to stdout. :)
Good point, see REDIRECTION in bash man. As you can see, the manual is far from clear on this:

Quote:
The general format for redirecting output is:

[n]>word
[...]
>&word
[...] is semantically equiva‐
lent to

>word 2>&1
[...]
The operator

[n]>&word

is used similarly to duplicate output file descriptors. (That is: "If word expands to one or
more digits, the file descriptor denoted by n is made to be a copy of
that file descriptor.", doru's note) If n is not
specified, the standard output (file descriptor 1) is used. If the
digits in word do not specify a file descriptor open for output, a re‐
direction error occurs. As a special case, if n is omitted, and word
does not expand to one or more digits, the standard output and standard
error are redirected as described previously.

Last edited by doru; 11-22-2010 at 12:12 PM. Reason: completion
 
Old 11-22-2010, 10:27 AM   #14
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Servers: Debian Squeeze and Wheezy. Desktop: Slackware64 14.0. Netbook: Slackware 13.37
Posts: 8,563
Blog Entries: 29

Rep: Reputation: 1179Reputation: 1179Reputation: 1179Reputation: 1179Reputation: 1179Reputation: 1179Reputation: 1179Reputation: 1179Reputation: 1179
Quote:
Originally Posted by haertig View Post
The eagle-eyed observer will notice an apparent discrepancy for "|" ...

ls -l 2>&1 | tee file.txt will log BOTH stdout and stderr from ls to file.txt. But at this time, when stderr was redirected to the same place as stdout, stdout had not yet been redirected to tee via the "|". Hmmm ... gotcha! Just one of those things. Never fails - when you try to rationalize your way through something logically ... you run into an exception! This is one of those things were experience tells me "I know it works this way", but when you press me with the "why?" question, I have to hem and haw and say "Because that's the way it is!"
It makes sense in the light of the shell's operation. The "|" is actioned in "3. Parses the tokens into simple and compound commands" and the ">"s are actioned in "5. Performs any necessary redirections ..." so, in this case, the ls command's stdout is already configured for redirection to the tee command by the time the ">"s are processed.
 
1 members found this post helpful.
Old 11-22-2010, 12:26 PM   #15
doru
Member
 
Registered: Sep 2008
Distribution: Ubuntu 8.04 LTS Server
Posts: 89

Rep: Reputation: 16
bash man

Quote:
Originally Posted by catkin View Post
It makes sense in the light of the shell's operation. The "|" is actioned in "3. Parses the tokens into simple and compound commands" and the ">"s are actioned in "5. Performs any necessary redirections ..." so, in this case, the ls command's stdout is already configured for redirection to the tee command by the time the ">"s are processed.
Thank you. My Ubuntu 10.04 bash man does not really say that.
 
  


Reply

Tags
pipe, redirect, stderr, stdout, tee


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
How to redirect output to a file? mus1402 Linux - Newbie 2 02-05-2006 10:42 AM
redirect screen output to file timbuck Linux - Software 5 12-09-2005 07:57 PM
how to redirect the soundcard output to a file? jr0 Linux - General 2 10-31-2005 07:29 AM
Is there a way in Linux/Unix bash to turn off output or redirect to a file jimwelc Linux - Newbie 6 01-06-2005 04:56 AM
output from cpio won't redirect to file rawii Programming 5 01-27-2004 02:49 PM


All times are GMT -5. The time now is 08:03 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration