Is this a typo in Bash manual's redirection section?How does redirecting stdout to stderr workwhat is...
Charges from Dollar General have never shown up on my debit card. How can I resolve this?
What is Ferb's name short for?
Problem with NSolve with Logarithm
What happens when supercritical fuel tanks deplete below critical point?
Did I Traumatize My Puppy?
Encountering former, abusive advisor at a conference
On notice period - coworker I need to train is giving me the silent treatment
Digit Date Range
How to find the sum of digits of a number whose prime factorisation is given
Is it possible for a country to develop the equivalent of a Second Industrial Revolution while under a war of attrition?
Labeling lines that are not within polygons using field calculator
Sum of all digits in a string
Replace spaces with comma but not in the whole line
I run daily 5kms but I cant seem to improve stamina when playing soccer
Is it allowed to let the engine of an aircraft idle without a pilot in the plane. (For both helicopters and aeroplanes)
How were Kurds involved (or not) in the invasion of Normandy?
Car as a good investment
Why do military jets sometimes have elevators in a depressed position when parked?
How to deal with people whose priority is to not get blamed?
Did the US push the Kurds to lower their defences against Turkey in the months preceding the latest Turkish military operation against them?
Why is my paper "under review" if it contains no results?
Did Terry Pratchett ever explain the inspiration behind the Luggage?
If you revoke a certificate authority's certificate, do all of the certificates it issued become invalid as well?
How to figure out key from key signature?
Is this a typo in Bash manual's redirection section?
How does redirecting stdout to stderr workwhat is >> symbol and >& in unix/Linux?How to grep standard error stream (stderr)?Restoring output to the terminal after having issued “exec &>filename”Caveats with Stdout/Stderr Redirection to Files?Do not wait until the return for Shell redirectionSeparate dd data from output through netcat to parse outputAppend string on redirectProcess substitution and redirection using tee
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{
margin-bottom:0;
}
Note that the order of redirections is significant. For example, the command
ls > dirlist 2>&1
directs both standard output and standard error to the file dirlist,
while the command
ls 2>&1 > dirlist
directs only the standard output to file dirlist, because the
standard error was duplicated from the standard output before the standard
output was redirected to dirlist.
Now, that last part is confusing to me. In that case, any standard error would be printed to the terminal and any STDOUT would go to the dirlist file. That is what would happen, but that is not how I understand the manual.
It seems like it should say "because the standard error was duplicated from the standard output AFTER the standard output was redirected to dirlist". If STDERR was sent to STDOUT before STDOUT was directed to a file, then wouldn't the file contain STDOUT AND STDERR?
Can someone please clear this up for me? Is it just poor reading comprehension on my part? The use of the word duplication seems a little strange to me in this context. Perhaps that is throwing me.
bash shell io-redirection
add a comment
|
Note that the order of redirections is significant. For example, the command
ls > dirlist 2>&1
directs both standard output and standard error to the file dirlist,
while the command
ls 2>&1 > dirlist
directs only the standard output to file dirlist, because the
standard error was duplicated from the standard output before the standard
output was redirected to dirlist.
Now, that last part is confusing to me. In that case, any standard error would be printed to the terminal and any STDOUT would go to the dirlist file. That is what would happen, but that is not how I understand the manual.
It seems like it should say "because the standard error was duplicated from the standard output AFTER the standard output was redirected to dirlist". If STDERR was sent to STDOUT before STDOUT was directed to a file, then wouldn't the file contain STDOUT AND STDERR?
Can someone please clear this up for me? Is it just poor reading comprehension on my part? The use of the word duplication seems a little strange to me in this context. Perhaps that is throwing me.
bash shell io-redirection
See stackoverflow.com/q/14615653/1030675
– choroba
Jul 24 '13 at 15:48
1
A classic case of mixing up operations that are "by value" vs "by reference". When you duplicate a file descriptor it is a by value operation. In programming, aftera = 1; b = a; a = 2you expecta == 2 && b == 1to be true. The redirection2>&1is similar to theb = aassignment - it is by value, not by reference.2>&1does not wed file descriptor 2 to file descriptor 1 for all of eternity - they are still 2 distinct file descriptors, who happen to point to the same file.
– jw013
Jul 30 '13 at 20:15
add a comment
|
Note that the order of redirections is significant. For example, the command
ls > dirlist 2>&1
directs both standard output and standard error to the file dirlist,
while the command
ls 2>&1 > dirlist
directs only the standard output to file dirlist, because the
standard error was duplicated from the standard output before the standard
output was redirected to dirlist.
Now, that last part is confusing to me. In that case, any standard error would be printed to the terminal and any STDOUT would go to the dirlist file. That is what would happen, but that is not how I understand the manual.
It seems like it should say "because the standard error was duplicated from the standard output AFTER the standard output was redirected to dirlist". If STDERR was sent to STDOUT before STDOUT was directed to a file, then wouldn't the file contain STDOUT AND STDERR?
Can someone please clear this up for me? Is it just poor reading comprehension on my part? The use of the word duplication seems a little strange to me in this context. Perhaps that is throwing me.
bash shell io-redirection
Note that the order of redirections is significant. For example, the command
ls > dirlist 2>&1
directs both standard output and standard error to the file dirlist,
while the command
ls 2>&1 > dirlist
directs only the standard output to file dirlist, because the
standard error was duplicated from the standard output before the standard
output was redirected to dirlist.
Now, that last part is confusing to me. In that case, any standard error would be printed to the terminal and any STDOUT would go to the dirlist file. That is what would happen, but that is not how I understand the manual.
It seems like it should say "because the standard error was duplicated from the standard output AFTER the standard output was redirected to dirlist". If STDERR was sent to STDOUT before STDOUT was directed to a file, then wouldn't the file contain STDOUT AND STDERR?
Can someone please clear this up for me? Is it just poor reading comprehension on my part? The use of the word duplication seems a little strange to me in this context. Perhaps that is throwing me.
bash shell io-redirection
bash shell io-redirection
edited Jul 24 '13 at 22:26
Gilles
579k141 gold badges1195 silver badges1708 bronze badges
579k141 gold badges1195 silver badges1708 bronze badges
asked Jul 24 '13 at 15:40
Gregg LeventhalGregg Leventhal
3,21113 gold badges48 silver badges81 bronze badges
3,21113 gold badges48 silver badges81 bronze badges
See stackoverflow.com/q/14615653/1030675
– choroba
Jul 24 '13 at 15:48
1
A classic case of mixing up operations that are "by value" vs "by reference". When you duplicate a file descriptor it is a by value operation. In programming, aftera = 1; b = a; a = 2you expecta == 2 && b == 1to be true. The redirection2>&1is similar to theb = aassignment - it is by value, not by reference.2>&1does not wed file descriptor 2 to file descriptor 1 for all of eternity - they are still 2 distinct file descriptors, who happen to point to the same file.
– jw013
Jul 30 '13 at 20:15
add a comment
|
See stackoverflow.com/q/14615653/1030675
– choroba
Jul 24 '13 at 15:48
1
A classic case of mixing up operations that are "by value" vs "by reference". When you duplicate a file descriptor it is a by value operation. In programming, aftera = 1; b = a; a = 2you expecta == 2 && b == 1to be true. The redirection2>&1is similar to theb = aassignment - it is by value, not by reference.2>&1does not wed file descriptor 2 to file descriptor 1 for all of eternity - they are still 2 distinct file descriptors, who happen to point to the same file.
– jw013
Jul 30 '13 at 20:15
See stackoverflow.com/q/14615653/1030675
– choroba
Jul 24 '13 at 15:48
See stackoverflow.com/q/14615653/1030675
– choroba
Jul 24 '13 at 15:48
1
1
A classic case of mixing up operations that are "by value" vs "by reference". When you duplicate a file descriptor it is a by value operation. In programming, after
a = 1; b = a; a = 2 you expect a == 2 && b == 1 to be true. The redirection 2>&1 is similar to the b = a assignment - it is by value, not by reference. 2>&1 does not wed file descriptor 2 to file descriptor 1 for all of eternity - they are still 2 distinct file descriptors, who happen to point to the same file.– jw013
Jul 30 '13 at 20:15
A classic case of mixing up operations that are "by value" vs "by reference". When you duplicate a file descriptor it is a by value operation. In programming, after
a = 1; b = a; a = 2 you expect a == 2 && b == 1 to be true. The redirection 2>&1 is similar to the b = a assignment - it is by value, not by reference. 2>&1 does not wed file descriptor 2 to file descriptor 1 for all of eternity - they are still 2 distinct file descriptors, who happen to point to the same file.– jw013
Jul 30 '13 at 20:15
add a comment
|
4 Answers
4
active
oldest
votes
Duplication is really the important part here.
Let's see where the file descriptors are going to before redirection. This is normally the current terminal, e.g.:
STDOUT ---> /dev/pts/1
STDERR ---> /dev/pts/1
Now, if we call ls -l without redirection, output and error messages go to my terminal under /dev/pts/1.
If we first redirect the STDOUT to a file (ls -l > dirlist), it looks like this:
STDOUT ---> /home/bon/dirlist
STDERR ---> /dev/pts/1
When we then redirect STDERR to a duplicate of STDOUT's file descriptor (ls -l > dirlist 2>&1), STDERR goes to a duplicate of /home/bon/dirlist:
STDOUT ---> /home/bon/dirlist
STDERR ---> /home/bon/dirlist
If we would first redirect STDERR to a duplicate of STDOUT's file descriptor (ls -l 2>&1):
STDOUT ---> /dev/pts/1
STDERR ---> /dev/pts/1
and then STDOUT to a file (ls -l 2>&1 > dirlist), we would get this:
STDOUT ---> /home/bon/dirlist
STDERR ---> /dev/pts/1
Here, STDERR is still going to the terminal.
You see, the order in the man page is correct.
Testing Redirection
Now, you can test that yourself. Using ls -l /proc/$$/fd/, you see where STDOUT (with fd 1) and STDERR (with fd 2), are going for the current process:
$ ls -l /proc/$$/fd/
total 0
lrwx------ 1 bon bon 64 Jul 24 18:19 0 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 18:19 1 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 07:41 2 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 18:19 255 -> /dev/pts/1
Let's create a small shell script that shows where your file descriptors are pointed. This way, we always get the state when calling ls, including any redirection from the calling shell.
$ cat > lookfd.sh
#!/bin/sh
ls -l /proc/$$/fd/
^D
$ chmod +x lookfd.sh
(With CtrlD, you send an end-of-file and so stop the cat command reading from STDIN.)
Now, call this script with varying combinations of redirection:
$ ./lookfd.sh
total 0
lrwx------ 1 bon bon 64 Jul 24 19:08 0 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 19:08 1 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 19:08 2 -> /dev/pts/1
lr-x------ 1 bon bon 64 Jul 24 19:08 255 -> /home/bon/lookfd.sh
$ ./lookfd.sh > foo.out
$ cat foo.out
total 0
lrwx------ 1 bon bon 64 Jul 24 19:10 0 -> /dev/pts/1
l-wx------ 1 bon bon 64 Jul 24 19:10 1 -> /home/bon/foo.out
lrwx------ 1 bon bon 64 Jul 24 19:10 2 -> /dev/pts/1
lr-x------ 1 bon bon 64 Jul 24 19:10 255 -> /home/bon/lookfd.sh
$ ./lookfd.sh 2>&1 > foo.out
$ cat foo.out
total 0
lrwx------ 1 bon bon 64 Jul 24 19:10 0 -> /dev/pts/1
l-wx------ 1 bon bon 64 Jul 24 19:10 1 -> /home/bon/foo.out
lrwx------ 1 bon bon 64 Jul 24 19:10 2 -> /dev/pts/1
lr-x------ 1 bon bon 64 Jul 24 19:10 255 -> /home/bon/lookfd.sh
$ ./lookfd.sh > foo.out 2>&1
$ cat foo.out
total 0
lrwx------ 1 bon bon 64 Jul 24 19:11 0 -> /dev/pts/1
l-wx------ 1 bon bon 64 Jul 24 19:11 1 -> /home/bon/foo.out
l-wx------ 1 bon bon 64 Jul 24 19:11 2 -> /home/bon/foo.out
lr-x------ 1 bon bon 64 Jul 24 19:11 255 -> /home/bon/lookfd.sh
You can see, that the file descriptors 1 (for STDOUT) and 2 (for STDERR) vary. For fun, you could also redirect STDIN and see the result:
$ ./lookfd.sh < /dev/zero
total 0
lr-x------ 1 bon bon 64 Jul 24 19:18 0 -> /dev/zero
lrwx------ 1 bon bon 64 Jul 24 19:18 1 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 19:18 2 -> /dev/pts/1
lr-x------ 1 bon bon 64 Jul 24 19:18 255 -> /home/bon/lookfd.sh
(Question left to the reader: Where does file descriptor 255 point? ;-))
+1 - excellent answer. Extremely well written and terrific examples. Thank you!!!
– slm♦
Jul 24 '13 at 18:50
I see, I think my misunderstanding was that the redirection would be persistent for all following commands, so that any STDERR for the rest of the line would go to STDOUT.
– Gregg Leventhal
Jul 31 '13 at 13:56
add a comment
|
No, the manual is right.
If at first 1 points to the terminal, and 2 also to the terminal, then:
command 2>&1 1>somewhere
redirection evaluatino will happen from left to right.
So it will FIRST evaluate 2>&1, and thus FIRST copy what fd 1 used to point to (ie, the file descriptor of the terminal, usually /dev/tty) into fd 2.
So at that point fd 2 now points to where fd 1 used to point to (the terminal)
And THEN it evaluates the 1>somewhere part, and thus will copy the file descriptor of somewhere in fd 1 (so at that point, fd 1 now points to somewhere, and fd 2 still points to the terminal)
So it does indeed print 1 into "somewhere" and 2 into the terminal, as 2 was duplicated from 1 BEFORE 1 has been changed.
The other order:
command 1>somewhere 2>&1
will first redirect fd 1 to somewhere, and then copy that same reference into fd 2, so at the end 2 also points to somewhere.
But they are not "linked" from now on. Each can still be redirected separately.
ex:
command 1>somewhere 2>&1
exec 2>/dev/null
At the end of that one, fd 1 points to somewhere, and fd 2 is directed to /dev/null
Usual names for fd 1 is STDOUT (standard output), and usual name for fd 2 is STDERR (standard error, as it's commonly used to display errors without interfering with STDOUT)
@Michael-mrozek : thanks for the edit, but I insist on saying "copy" instead of "duplicate" as "duplicate" could lead one to believe that from now on both are "the same thing", which is not true. ex:cmd 1>somewhere 2>&1 ; exec 2>/dev/null: after the exec, only 2 has been redirected to /dev/null (1 is still going to "somewhere"). I do need help to come up with a way to say "what 1 points to" instead of "the fd 1", however... as that is also confusing...
– Olivier Dulac
Jul 24 '13 at 17:19
1
I'm not sure what you mean; you're the one who changed it from "copy" to "duplicate". All I did was capitalize and format things, I didn't change a word
– Michael Mrozek♦
Jul 24 '13 at 17:23
doh... ^^ sorry. And I edited again to reformulate to make more precise what is copied into what ^^
– Olivier Dulac
Jul 24 '13 at 17:26
add a comment
|
I think the confusing part here is the misapprehension that redirecting stderr to stdout actually connects the two streams.
A perfectly reasonable idea but what happens when you write 2>&1 is stderr takes a peekaboo at what stdout is writing to and writes to the same place itself. Therefore if you subsequently tell stdout to go write somewhere else it has no effect on the destination of stderr which has already been moved.
I think it's a tad counterintuitive myself but that's how it works. Set up where you want to write to first then tell everyone "copy me".
Hope that clarifies...
add a comment
|
DUPLICATION...
is important, but rather in the sense that it is the source of much confusion. It is really quite simple. This answer is just a "radical" illustration.
The accepted answer is good, but too long and it emphasizes "duplicatition".
The Q wisely ends with:
The use of the word duplication seems a little strange to me in
this context. Perhaps that is throwing me.
I use bash notation and define variables "one" and "two" as filehandles "1" and "2". The (output) redirection operator > is an assignment =. & and $ mean "value" of.
The man bash examples (with default "1" added)
ls 1>dirlist 2>&1 # both to dirlist
ls 2>&1 1>dirlist # 1 to dirlist, 2 stays on tty/screen
become:
one=dirlist two=$one
and
two=$one one=dirlist
And even this is non-automatic to me, and some others I guess. The first line leaves you with $one and $two both containing "dirlist". Of course.
The second line starts with a useless assignment. Both start by definition with "TTY" (a bit symbolic) as their direction; no value is changed by this assignment, and with variables as with filehandles, nothing is magically linked. Variable two is not affected by the following one=dirlist. Of course not.
Sombody here (6 years ago) suggested "point to" instead of "copy" or "duplicate", and then realized: that would be confusing too.
This duplication or pointer semantic is not even needed. Maybe it's the ampersand that needs more attention. The "value of" operator/token/whatever.
If - and only if - you are looking for a way to get a surprising job number on your console, then a "done" message plus as a bonus a file named "2", then you go:
ls 1>2& 2>/dev/null
It reads naturally as "copy"/"duplicate" 1 to 2, and then both together to null. But the idea is wrong, and also the syntax. (but no syntax error, it is valid)
The right way to plan it is to redirect any of the two to null, and then redirect the OTHER to the SAME place:
ls 1>/dev/null 2>&1
# or
ls 2>/dev/null 1>&2
(the leading "1" can be left away)
(OK the acc. A is not too long, but is too much of a list - or: very good visualisation, not so good explanation)
add a comment
|
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "106"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/4.0/"u003ecc by-sa 4.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f84279%2fis-this-a-typo-in-bash-manuals-redirection-section%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
Duplication is really the important part here.
Let's see where the file descriptors are going to before redirection. This is normally the current terminal, e.g.:
STDOUT ---> /dev/pts/1
STDERR ---> /dev/pts/1
Now, if we call ls -l without redirection, output and error messages go to my terminal under /dev/pts/1.
If we first redirect the STDOUT to a file (ls -l > dirlist), it looks like this:
STDOUT ---> /home/bon/dirlist
STDERR ---> /dev/pts/1
When we then redirect STDERR to a duplicate of STDOUT's file descriptor (ls -l > dirlist 2>&1), STDERR goes to a duplicate of /home/bon/dirlist:
STDOUT ---> /home/bon/dirlist
STDERR ---> /home/bon/dirlist
If we would first redirect STDERR to a duplicate of STDOUT's file descriptor (ls -l 2>&1):
STDOUT ---> /dev/pts/1
STDERR ---> /dev/pts/1
and then STDOUT to a file (ls -l 2>&1 > dirlist), we would get this:
STDOUT ---> /home/bon/dirlist
STDERR ---> /dev/pts/1
Here, STDERR is still going to the terminal.
You see, the order in the man page is correct.
Testing Redirection
Now, you can test that yourself. Using ls -l /proc/$$/fd/, you see where STDOUT (with fd 1) and STDERR (with fd 2), are going for the current process:
$ ls -l /proc/$$/fd/
total 0
lrwx------ 1 bon bon 64 Jul 24 18:19 0 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 18:19 1 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 07:41 2 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 18:19 255 -> /dev/pts/1
Let's create a small shell script that shows where your file descriptors are pointed. This way, we always get the state when calling ls, including any redirection from the calling shell.
$ cat > lookfd.sh
#!/bin/sh
ls -l /proc/$$/fd/
^D
$ chmod +x lookfd.sh
(With CtrlD, you send an end-of-file and so stop the cat command reading from STDIN.)
Now, call this script with varying combinations of redirection:
$ ./lookfd.sh
total 0
lrwx------ 1 bon bon 64 Jul 24 19:08 0 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 19:08 1 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 19:08 2 -> /dev/pts/1
lr-x------ 1 bon bon 64 Jul 24 19:08 255 -> /home/bon/lookfd.sh
$ ./lookfd.sh > foo.out
$ cat foo.out
total 0
lrwx------ 1 bon bon 64 Jul 24 19:10 0 -> /dev/pts/1
l-wx------ 1 bon bon 64 Jul 24 19:10 1 -> /home/bon/foo.out
lrwx------ 1 bon bon 64 Jul 24 19:10 2 -> /dev/pts/1
lr-x------ 1 bon bon 64 Jul 24 19:10 255 -> /home/bon/lookfd.sh
$ ./lookfd.sh 2>&1 > foo.out
$ cat foo.out
total 0
lrwx------ 1 bon bon 64 Jul 24 19:10 0 -> /dev/pts/1
l-wx------ 1 bon bon 64 Jul 24 19:10 1 -> /home/bon/foo.out
lrwx------ 1 bon bon 64 Jul 24 19:10 2 -> /dev/pts/1
lr-x------ 1 bon bon 64 Jul 24 19:10 255 -> /home/bon/lookfd.sh
$ ./lookfd.sh > foo.out 2>&1
$ cat foo.out
total 0
lrwx------ 1 bon bon 64 Jul 24 19:11 0 -> /dev/pts/1
l-wx------ 1 bon bon 64 Jul 24 19:11 1 -> /home/bon/foo.out
l-wx------ 1 bon bon 64 Jul 24 19:11 2 -> /home/bon/foo.out
lr-x------ 1 bon bon 64 Jul 24 19:11 255 -> /home/bon/lookfd.sh
You can see, that the file descriptors 1 (for STDOUT) and 2 (for STDERR) vary. For fun, you could also redirect STDIN and see the result:
$ ./lookfd.sh < /dev/zero
total 0
lr-x------ 1 bon bon 64 Jul 24 19:18 0 -> /dev/zero
lrwx------ 1 bon bon 64 Jul 24 19:18 1 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 19:18 2 -> /dev/pts/1
lr-x------ 1 bon bon 64 Jul 24 19:18 255 -> /home/bon/lookfd.sh
(Question left to the reader: Where does file descriptor 255 point? ;-))
+1 - excellent answer. Extremely well written and terrific examples. Thank you!!!
– slm♦
Jul 24 '13 at 18:50
I see, I think my misunderstanding was that the redirection would be persistent for all following commands, so that any STDERR for the rest of the line would go to STDOUT.
– Gregg Leventhal
Jul 31 '13 at 13:56
add a comment
|
Duplication is really the important part here.
Let's see where the file descriptors are going to before redirection. This is normally the current terminal, e.g.:
STDOUT ---> /dev/pts/1
STDERR ---> /dev/pts/1
Now, if we call ls -l without redirection, output and error messages go to my terminal under /dev/pts/1.
If we first redirect the STDOUT to a file (ls -l > dirlist), it looks like this:
STDOUT ---> /home/bon/dirlist
STDERR ---> /dev/pts/1
When we then redirect STDERR to a duplicate of STDOUT's file descriptor (ls -l > dirlist 2>&1), STDERR goes to a duplicate of /home/bon/dirlist:
STDOUT ---> /home/bon/dirlist
STDERR ---> /home/bon/dirlist
If we would first redirect STDERR to a duplicate of STDOUT's file descriptor (ls -l 2>&1):
STDOUT ---> /dev/pts/1
STDERR ---> /dev/pts/1
and then STDOUT to a file (ls -l 2>&1 > dirlist), we would get this:
STDOUT ---> /home/bon/dirlist
STDERR ---> /dev/pts/1
Here, STDERR is still going to the terminal.
You see, the order in the man page is correct.
Testing Redirection
Now, you can test that yourself. Using ls -l /proc/$$/fd/, you see where STDOUT (with fd 1) and STDERR (with fd 2), are going for the current process:
$ ls -l /proc/$$/fd/
total 0
lrwx------ 1 bon bon 64 Jul 24 18:19 0 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 18:19 1 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 07:41 2 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 18:19 255 -> /dev/pts/1
Let's create a small shell script that shows where your file descriptors are pointed. This way, we always get the state when calling ls, including any redirection from the calling shell.
$ cat > lookfd.sh
#!/bin/sh
ls -l /proc/$$/fd/
^D
$ chmod +x lookfd.sh
(With CtrlD, you send an end-of-file and so stop the cat command reading from STDIN.)
Now, call this script with varying combinations of redirection:
$ ./lookfd.sh
total 0
lrwx------ 1 bon bon 64 Jul 24 19:08 0 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 19:08 1 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 19:08 2 -> /dev/pts/1
lr-x------ 1 bon bon 64 Jul 24 19:08 255 -> /home/bon/lookfd.sh
$ ./lookfd.sh > foo.out
$ cat foo.out
total 0
lrwx------ 1 bon bon 64 Jul 24 19:10 0 -> /dev/pts/1
l-wx------ 1 bon bon 64 Jul 24 19:10 1 -> /home/bon/foo.out
lrwx------ 1 bon bon 64 Jul 24 19:10 2 -> /dev/pts/1
lr-x------ 1 bon bon 64 Jul 24 19:10 255 -> /home/bon/lookfd.sh
$ ./lookfd.sh 2>&1 > foo.out
$ cat foo.out
total 0
lrwx------ 1 bon bon 64 Jul 24 19:10 0 -> /dev/pts/1
l-wx------ 1 bon bon 64 Jul 24 19:10 1 -> /home/bon/foo.out
lrwx------ 1 bon bon 64 Jul 24 19:10 2 -> /dev/pts/1
lr-x------ 1 bon bon 64 Jul 24 19:10 255 -> /home/bon/lookfd.sh
$ ./lookfd.sh > foo.out 2>&1
$ cat foo.out
total 0
lrwx------ 1 bon bon 64 Jul 24 19:11 0 -> /dev/pts/1
l-wx------ 1 bon bon 64 Jul 24 19:11 1 -> /home/bon/foo.out
l-wx------ 1 bon bon 64 Jul 24 19:11 2 -> /home/bon/foo.out
lr-x------ 1 bon bon 64 Jul 24 19:11 255 -> /home/bon/lookfd.sh
You can see, that the file descriptors 1 (for STDOUT) and 2 (for STDERR) vary. For fun, you could also redirect STDIN and see the result:
$ ./lookfd.sh < /dev/zero
total 0
lr-x------ 1 bon bon 64 Jul 24 19:18 0 -> /dev/zero
lrwx------ 1 bon bon 64 Jul 24 19:18 1 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 19:18 2 -> /dev/pts/1
lr-x------ 1 bon bon 64 Jul 24 19:18 255 -> /home/bon/lookfd.sh
(Question left to the reader: Where does file descriptor 255 point? ;-))
+1 - excellent answer. Extremely well written and terrific examples. Thank you!!!
– slm♦
Jul 24 '13 at 18:50
I see, I think my misunderstanding was that the redirection would be persistent for all following commands, so that any STDERR for the rest of the line would go to STDOUT.
– Gregg Leventhal
Jul 31 '13 at 13:56
add a comment
|
Duplication is really the important part here.
Let's see where the file descriptors are going to before redirection. This is normally the current terminal, e.g.:
STDOUT ---> /dev/pts/1
STDERR ---> /dev/pts/1
Now, if we call ls -l without redirection, output and error messages go to my terminal under /dev/pts/1.
If we first redirect the STDOUT to a file (ls -l > dirlist), it looks like this:
STDOUT ---> /home/bon/dirlist
STDERR ---> /dev/pts/1
When we then redirect STDERR to a duplicate of STDOUT's file descriptor (ls -l > dirlist 2>&1), STDERR goes to a duplicate of /home/bon/dirlist:
STDOUT ---> /home/bon/dirlist
STDERR ---> /home/bon/dirlist
If we would first redirect STDERR to a duplicate of STDOUT's file descriptor (ls -l 2>&1):
STDOUT ---> /dev/pts/1
STDERR ---> /dev/pts/1
and then STDOUT to a file (ls -l 2>&1 > dirlist), we would get this:
STDOUT ---> /home/bon/dirlist
STDERR ---> /dev/pts/1
Here, STDERR is still going to the terminal.
You see, the order in the man page is correct.
Testing Redirection
Now, you can test that yourself. Using ls -l /proc/$$/fd/, you see where STDOUT (with fd 1) and STDERR (with fd 2), are going for the current process:
$ ls -l /proc/$$/fd/
total 0
lrwx------ 1 bon bon 64 Jul 24 18:19 0 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 18:19 1 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 07:41 2 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 18:19 255 -> /dev/pts/1
Let's create a small shell script that shows where your file descriptors are pointed. This way, we always get the state when calling ls, including any redirection from the calling shell.
$ cat > lookfd.sh
#!/bin/sh
ls -l /proc/$$/fd/
^D
$ chmod +x lookfd.sh
(With CtrlD, you send an end-of-file and so stop the cat command reading from STDIN.)
Now, call this script with varying combinations of redirection:
$ ./lookfd.sh
total 0
lrwx------ 1 bon bon 64 Jul 24 19:08 0 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 19:08 1 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 19:08 2 -> /dev/pts/1
lr-x------ 1 bon bon 64 Jul 24 19:08 255 -> /home/bon/lookfd.sh
$ ./lookfd.sh > foo.out
$ cat foo.out
total 0
lrwx------ 1 bon bon 64 Jul 24 19:10 0 -> /dev/pts/1
l-wx------ 1 bon bon 64 Jul 24 19:10 1 -> /home/bon/foo.out
lrwx------ 1 bon bon 64 Jul 24 19:10 2 -> /dev/pts/1
lr-x------ 1 bon bon 64 Jul 24 19:10 255 -> /home/bon/lookfd.sh
$ ./lookfd.sh 2>&1 > foo.out
$ cat foo.out
total 0
lrwx------ 1 bon bon 64 Jul 24 19:10 0 -> /dev/pts/1
l-wx------ 1 bon bon 64 Jul 24 19:10 1 -> /home/bon/foo.out
lrwx------ 1 bon bon 64 Jul 24 19:10 2 -> /dev/pts/1
lr-x------ 1 bon bon 64 Jul 24 19:10 255 -> /home/bon/lookfd.sh
$ ./lookfd.sh > foo.out 2>&1
$ cat foo.out
total 0
lrwx------ 1 bon bon 64 Jul 24 19:11 0 -> /dev/pts/1
l-wx------ 1 bon bon 64 Jul 24 19:11 1 -> /home/bon/foo.out
l-wx------ 1 bon bon 64 Jul 24 19:11 2 -> /home/bon/foo.out
lr-x------ 1 bon bon 64 Jul 24 19:11 255 -> /home/bon/lookfd.sh
You can see, that the file descriptors 1 (for STDOUT) and 2 (for STDERR) vary. For fun, you could also redirect STDIN and see the result:
$ ./lookfd.sh < /dev/zero
total 0
lr-x------ 1 bon bon 64 Jul 24 19:18 0 -> /dev/zero
lrwx------ 1 bon bon 64 Jul 24 19:18 1 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 19:18 2 -> /dev/pts/1
lr-x------ 1 bon bon 64 Jul 24 19:18 255 -> /home/bon/lookfd.sh
(Question left to the reader: Where does file descriptor 255 point? ;-))
Duplication is really the important part here.
Let's see where the file descriptors are going to before redirection. This is normally the current terminal, e.g.:
STDOUT ---> /dev/pts/1
STDERR ---> /dev/pts/1
Now, if we call ls -l without redirection, output and error messages go to my terminal under /dev/pts/1.
If we first redirect the STDOUT to a file (ls -l > dirlist), it looks like this:
STDOUT ---> /home/bon/dirlist
STDERR ---> /dev/pts/1
When we then redirect STDERR to a duplicate of STDOUT's file descriptor (ls -l > dirlist 2>&1), STDERR goes to a duplicate of /home/bon/dirlist:
STDOUT ---> /home/bon/dirlist
STDERR ---> /home/bon/dirlist
If we would first redirect STDERR to a duplicate of STDOUT's file descriptor (ls -l 2>&1):
STDOUT ---> /dev/pts/1
STDERR ---> /dev/pts/1
and then STDOUT to a file (ls -l 2>&1 > dirlist), we would get this:
STDOUT ---> /home/bon/dirlist
STDERR ---> /dev/pts/1
Here, STDERR is still going to the terminal.
You see, the order in the man page is correct.
Testing Redirection
Now, you can test that yourself. Using ls -l /proc/$$/fd/, you see where STDOUT (with fd 1) and STDERR (with fd 2), are going for the current process:
$ ls -l /proc/$$/fd/
total 0
lrwx------ 1 bon bon 64 Jul 24 18:19 0 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 18:19 1 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 07:41 2 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 18:19 255 -> /dev/pts/1
Let's create a small shell script that shows where your file descriptors are pointed. This way, we always get the state when calling ls, including any redirection from the calling shell.
$ cat > lookfd.sh
#!/bin/sh
ls -l /proc/$$/fd/
^D
$ chmod +x lookfd.sh
(With CtrlD, you send an end-of-file and so stop the cat command reading from STDIN.)
Now, call this script with varying combinations of redirection:
$ ./lookfd.sh
total 0
lrwx------ 1 bon bon 64 Jul 24 19:08 0 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 19:08 1 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 19:08 2 -> /dev/pts/1
lr-x------ 1 bon bon 64 Jul 24 19:08 255 -> /home/bon/lookfd.sh
$ ./lookfd.sh > foo.out
$ cat foo.out
total 0
lrwx------ 1 bon bon 64 Jul 24 19:10 0 -> /dev/pts/1
l-wx------ 1 bon bon 64 Jul 24 19:10 1 -> /home/bon/foo.out
lrwx------ 1 bon bon 64 Jul 24 19:10 2 -> /dev/pts/1
lr-x------ 1 bon bon 64 Jul 24 19:10 255 -> /home/bon/lookfd.sh
$ ./lookfd.sh 2>&1 > foo.out
$ cat foo.out
total 0
lrwx------ 1 bon bon 64 Jul 24 19:10 0 -> /dev/pts/1
l-wx------ 1 bon bon 64 Jul 24 19:10 1 -> /home/bon/foo.out
lrwx------ 1 bon bon 64 Jul 24 19:10 2 -> /dev/pts/1
lr-x------ 1 bon bon 64 Jul 24 19:10 255 -> /home/bon/lookfd.sh
$ ./lookfd.sh > foo.out 2>&1
$ cat foo.out
total 0
lrwx------ 1 bon bon 64 Jul 24 19:11 0 -> /dev/pts/1
l-wx------ 1 bon bon 64 Jul 24 19:11 1 -> /home/bon/foo.out
l-wx------ 1 bon bon 64 Jul 24 19:11 2 -> /home/bon/foo.out
lr-x------ 1 bon bon 64 Jul 24 19:11 255 -> /home/bon/lookfd.sh
You can see, that the file descriptors 1 (for STDOUT) and 2 (for STDERR) vary. For fun, you could also redirect STDIN and see the result:
$ ./lookfd.sh < /dev/zero
total 0
lr-x------ 1 bon bon 64 Jul 24 19:18 0 -> /dev/zero
lrwx------ 1 bon bon 64 Jul 24 19:18 1 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 19:18 2 -> /dev/pts/1
lr-x------ 1 bon bon 64 Jul 24 19:18 255 -> /home/bon/lookfd.sh
(Question left to the reader: Where does file descriptor 255 point? ;-))
edited Jul 24 '13 at 17:48
slm♦
271k77 gold badges588 silver badges732 bronze badges
271k77 gold badges588 silver badges732 bronze badges
answered Jul 24 '13 at 17:33
DubuDubu
2,65512 silver badges24 bronze badges
2,65512 silver badges24 bronze badges
+1 - excellent answer. Extremely well written and terrific examples. Thank you!!!
– slm♦
Jul 24 '13 at 18:50
I see, I think my misunderstanding was that the redirection would be persistent for all following commands, so that any STDERR for the rest of the line would go to STDOUT.
– Gregg Leventhal
Jul 31 '13 at 13:56
add a comment
|
+1 - excellent answer. Extremely well written and terrific examples. Thank you!!!
– slm♦
Jul 24 '13 at 18:50
I see, I think my misunderstanding was that the redirection would be persistent for all following commands, so that any STDERR for the rest of the line would go to STDOUT.
– Gregg Leventhal
Jul 31 '13 at 13:56
+1 - excellent answer. Extremely well written and terrific examples. Thank you!!!
– slm♦
Jul 24 '13 at 18:50
+1 - excellent answer. Extremely well written and terrific examples. Thank you!!!
– slm♦
Jul 24 '13 at 18:50
I see, I think my misunderstanding was that the redirection would be persistent for all following commands, so that any STDERR for the rest of the line would go to STDOUT.
– Gregg Leventhal
Jul 31 '13 at 13:56
I see, I think my misunderstanding was that the redirection would be persistent for all following commands, so that any STDERR for the rest of the line would go to STDOUT.
– Gregg Leventhal
Jul 31 '13 at 13:56
add a comment
|
No, the manual is right.
If at first 1 points to the terminal, and 2 also to the terminal, then:
command 2>&1 1>somewhere
redirection evaluatino will happen from left to right.
So it will FIRST evaluate 2>&1, and thus FIRST copy what fd 1 used to point to (ie, the file descriptor of the terminal, usually /dev/tty) into fd 2.
So at that point fd 2 now points to where fd 1 used to point to (the terminal)
And THEN it evaluates the 1>somewhere part, and thus will copy the file descriptor of somewhere in fd 1 (so at that point, fd 1 now points to somewhere, and fd 2 still points to the terminal)
So it does indeed print 1 into "somewhere" and 2 into the terminal, as 2 was duplicated from 1 BEFORE 1 has been changed.
The other order:
command 1>somewhere 2>&1
will first redirect fd 1 to somewhere, and then copy that same reference into fd 2, so at the end 2 also points to somewhere.
But they are not "linked" from now on. Each can still be redirected separately.
ex:
command 1>somewhere 2>&1
exec 2>/dev/null
At the end of that one, fd 1 points to somewhere, and fd 2 is directed to /dev/null
Usual names for fd 1 is STDOUT (standard output), and usual name for fd 2 is STDERR (standard error, as it's commonly used to display errors without interfering with STDOUT)
@Michael-mrozek : thanks for the edit, but I insist on saying "copy" instead of "duplicate" as "duplicate" could lead one to believe that from now on both are "the same thing", which is not true. ex:cmd 1>somewhere 2>&1 ; exec 2>/dev/null: after the exec, only 2 has been redirected to /dev/null (1 is still going to "somewhere"). I do need help to come up with a way to say "what 1 points to" instead of "the fd 1", however... as that is also confusing...
– Olivier Dulac
Jul 24 '13 at 17:19
1
I'm not sure what you mean; you're the one who changed it from "copy" to "duplicate". All I did was capitalize and format things, I didn't change a word
– Michael Mrozek♦
Jul 24 '13 at 17:23
doh... ^^ sorry. And I edited again to reformulate to make more precise what is copied into what ^^
– Olivier Dulac
Jul 24 '13 at 17:26
add a comment
|
No, the manual is right.
If at first 1 points to the terminal, and 2 also to the terminal, then:
command 2>&1 1>somewhere
redirection evaluatino will happen from left to right.
So it will FIRST evaluate 2>&1, and thus FIRST copy what fd 1 used to point to (ie, the file descriptor of the terminal, usually /dev/tty) into fd 2.
So at that point fd 2 now points to where fd 1 used to point to (the terminal)
And THEN it evaluates the 1>somewhere part, and thus will copy the file descriptor of somewhere in fd 1 (so at that point, fd 1 now points to somewhere, and fd 2 still points to the terminal)
So it does indeed print 1 into "somewhere" and 2 into the terminal, as 2 was duplicated from 1 BEFORE 1 has been changed.
The other order:
command 1>somewhere 2>&1
will first redirect fd 1 to somewhere, and then copy that same reference into fd 2, so at the end 2 also points to somewhere.
But they are not "linked" from now on. Each can still be redirected separately.
ex:
command 1>somewhere 2>&1
exec 2>/dev/null
At the end of that one, fd 1 points to somewhere, and fd 2 is directed to /dev/null
Usual names for fd 1 is STDOUT (standard output), and usual name for fd 2 is STDERR (standard error, as it's commonly used to display errors without interfering with STDOUT)
@Michael-mrozek : thanks for the edit, but I insist on saying "copy" instead of "duplicate" as "duplicate" could lead one to believe that from now on both are "the same thing", which is not true. ex:cmd 1>somewhere 2>&1 ; exec 2>/dev/null: after the exec, only 2 has been redirected to /dev/null (1 is still going to "somewhere"). I do need help to come up with a way to say "what 1 points to" instead of "the fd 1", however... as that is also confusing...
– Olivier Dulac
Jul 24 '13 at 17:19
1
I'm not sure what you mean; you're the one who changed it from "copy" to "duplicate". All I did was capitalize and format things, I didn't change a word
– Michael Mrozek♦
Jul 24 '13 at 17:23
doh... ^^ sorry. And I edited again to reformulate to make more precise what is copied into what ^^
– Olivier Dulac
Jul 24 '13 at 17:26
add a comment
|
No, the manual is right.
If at first 1 points to the terminal, and 2 also to the terminal, then:
command 2>&1 1>somewhere
redirection evaluatino will happen from left to right.
So it will FIRST evaluate 2>&1, and thus FIRST copy what fd 1 used to point to (ie, the file descriptor of the terminal, usually /dev/tty) into fd 2.
So at that point fd 2 now points to where fd 1 used to point to (the terminal)
And THEN it evaluates the 1>somewhere part, and thus will copy the file descriptor of somewhere in fd 1 (so at that point, fd 1 now points to somewhere, and fd 2 still points to the terminal)
So it does indeed print 1 into "somewhere" and 2 into the terminal, as 2 was duplicated from 1 BEFORE 1 has been changed.
The other order:
command 1>somewhere 2>&1
will first redirect fd 1 to somewhere, and then copy that same reference into fd 2, so at the end 2 also points to somewhere.
But they are not "linked" from now on. Each can still be redirected separately.
ex:
command 1>somewhere 2>&1
exec 2>/dev/null
At the end of that one, fd 1 points to somewhere, and fd 2 is directed to /dev/null
Usual names for fd 1 is STDOUT (standard output), and usual name for fd 2 is STDERR (standard error, as it's commonly used to display errors without interfering with STDOUT)
No, the manual is right.
If at first 1 points to the terminal, and 2 also to the terminal, then:
command 2>&1 1>somewhere
redirection evaluatino will happen from left to right.
So it will FIRST evaluate 2>&1, and thus FIRST copy what fd 1 used to point to (ie, the file descriptor of the terminal, usually /dev/tty) into fd 2.
So at that point fd 2 now points to where fd 1 used to point to (the terminal)
And THEN it evaluates the 1>somewhere part, and thus will copy the file descriptor of somewhere in fd 1 (so at that point, fd 1 now points to somewhere, and fd 2 still points to the terminal)
So it does indeed print 1 into "somewhere" and 2 into the terminal, as 2 was duplicated from 1 BEFORE 1 has been changed.
The other order:
command 1>somewhere 2>&1
will first redirect fd 1 to somewhere, and then copy that same reference into fd 2, so at the end 2 also points to somewhere.
But they are not "linked" from now on. Each can still be redirected separately.
ex:
command 1>somewhere 2>&1
exec 2>/dev/null
At the end of that one, fd 1 points to somewhere, and fd 2 is directed to /dev/null
Usual names for fd 1 is STDOUT (standard output), and usual name for fd 2 is STDERR (standard error, as it's commonly used to display errors without interfering with STDOUT)
edited Jul 24 '13 at 17:31
answered Jul 24 '13 at 17:08
Olivier DulacOlivier Dulac
3,99313 silver badges25 bronze badges
3,99313 silver badges25 bronze badges
@Michael-mrozek : thanks for the edit, but I insist on saying "copy" instead of "duplicate" as "duplicate" could lead one to believe that from now on both are "the same thing", which is not true. ex:cmd 1>somewhere 2>&1 ; exec 2>/dev/null: after the exec, only 2 has been redirected to /dev/null (1 is still going to "somewhere"). I do need help to come up with a way to say "what 1 points to" instead of "the fd 1", however... as that is also confusing...
– Olivier Dulac
Jul 24 '13 at 17:19
1
I'm not sure what you mean; you're the one who changed it from "copy" to "duplicate". All I did was capitalize and format things, I didn't change a word
– Michael Mrozek♦
Jul 24 '13 at 17:23
doh... ^^ sorry. And I edited again to reformulate to make more precise what is copied into what ^^
– Olivier Dulac
Jul 24 '13 at 17:26
add a comment
|
@Michael-mrozek : thanks for the edit, but I insist on saying "copy" instead of "duplicate" as "duplicate" could lead one to believe that from now on both are "the same thing", which is not true. ex:cmd 1>somewhere 2>&1 ; exec 2>/dev/null: after the exec, only 2 has been redirected to /dev/null (1 is still going to "somewhere"). I do need help to come up with a way to say "what 1 points to" instead of "the fd 1", however... as that is also confusing...
– Olivier Dulac
Jul 24 '13 at 17:19
1
I'm not sure what you mean; you're the one who changed it from "copy" to "duplicate". All I did was capitalize and format things, I didn't change a word
– Michael Mrozek♦
Jul 24 '13 at 17:23
doh... ^^ sorry. And I edited again to reformulate to make more precise what is copied into what ^^
– Olivier Dulac
Jul 24 '13 at 17:26
@Michael-mrozek : thanks for the edit, but I insist on saying "copy" instead of "duplicate" as "duplicate" could lead one to believe that from now on both are "the same thing", which is not true. ex:
cmd 1>somewhere 2>&1 ; exec 2>/dev/null : after the exec, only 2 has been redirected to /dev/null (1 is still going to "somewhere"). I do need help to come up with a way to say "what 1 points to" instead of "the fd 1", however... as that is also confusing...– Olivier Dulac
Jul 24 '13 at 17:19
@Michael-mrozek : thanks for the edit, but I insist on saying "copy" instead of "duplicate" as "duplicate" could lead one to believe that from now on both are "the same thing", which is not true. ex:
cmd 1>somewhere 2>&1 ; exec 2>/dev/null : after the exec, only 2 has been redirected to /dev/null (1 is still going to "somewhere"). I do need help to come up with a way to say "what 1 points to" instead of "the fd 1", however... as that is also confusing...– Olivier Dulac
Jul 24 '13 at 17:19
1
1
I'm not sure what you mean; you're the one who changed it from "copy" to "duplicate". All I did was capitalize and format things, I didn't change a word
– Michael Mrozek♦
Jul 24 '13 at 17:23
I'm not sure what you mean; you're the one who changed it from "copy" to "duplicate". All I did was capitalize and format things, I didn't change a word
– Michael Mrozek♦
Jul 24 '13 at 17:23
doh... ^^ sorry. And I edited again to reformulate to make more precise what is copied into what ^^
– Olivier Dulac
Jul 24 '13 at 17:26
doh... ^^ sorry. And I edited again to reformulate to make more precise what is copied into what ^^
– Olivier Dulac
Jul 24 '13 at 17:26
add a comment
|
I think the confusing part here is the misapprehension that redirecting stderr to stdout actually connects the two streams.
A perfectly reasonable idea but what happens when you write 2>&1 is stderr takes a peekaboo at what stdout is writing to and writes to the same place itself. Therefore if you subsequently tell stdout to go write somewhere else it has no effect on the destination of stderr which has already been moved.
I think it's a tad counterintuitive myself but that's how it works. Set up where you want to write to first then tell everyone "copy me".
Hope that clarifies...
add a comment
|
I think the confusing part here is the misapprehension that redirecting stderr to stdout actually connects the two streams.
A perfectly reasonable idea but what happens when you write 2>&1 is stderr takes a peekaboo at what stdout is writing to and writes to the same place itself. Therefore if you subsequently tell stdout to go write somewhere else it has no effect on the destination of stderr which has already been moved.
I think it's a tad counterintuitive myself but that's how it works. Set up where you want to write to first then tell everyone "copy me".
Hope that clarifies...
add a comment
|
I think the confusing part here is the misapprehension that redirecting stderr to stdout actually connects the two streams.
A perfectly reasonable idea but what happens when you write 2>&1 is stderr takes a peekaboo at what stdout is writing to and writes to the same place itself. Therefore if you subsequently tell stdout to go write somewhere else it has no effect on the destination of stderr which has already been moved.
I think it's a tad counterintuitive myself but that's how it works. Set up where you want to write to first then tell everyone "copy me".
Hope that clarifies...
I think the confusing part here is the misapprehension that redirecting stderr to stdout actually connects the two streams.
A perfectly reasonable idea but what happens when you write 2>&1 is stderr takes a peekaboo at what stdout is writing to and writes to the same place itself. Therefore if you subsequently tell stdout to go write somewhere else it has no effect on the destination of stderr which has already been moved.
I think it's a tad counterintuitive myself but that's how it works. Set up where you want to write to first then tell everyone "copy me".
Hope that clarifies...
edited Jul 30 '13 at 1:03
jasonwryan
53.5k14 gold badges141 silver badges195 bronze badges
53.5k14 gold badges141 silver badges195 bronze badges
answered Jul 30 '13 at 0:26
jrichemontjrichemont
112 bronze badges
112 bronze badges
add a comment
|
add a comment
|
DUPLICATION...
is important, but rather in the sense that it is the source of much confusion. It is really quite simple. This answer is just a "radical" illustration.
The accepted answer is good, but too long and it emphasizes "duplicatition".
The Q wisely ends with:
The use of the word duplication seems a little strange to me in
this context. Perhaps that is throwing me.
I use bash notation and define variables "one" and "two" as filehandles "1" and "2". The (output) redirection operator > is an assignment =. & and $ mean "value" of.
The man bash examples (with default "1" added)
ls 1>dirlist 2>&1 # both to dirlist
ls 2>&1 1>dirlist # 1 to dirlist, 2 stays on tty/screen
become:
one=dirlist two=$one
and
two=$one one=dirlist
And even this is non-automatic to me, and some others I guess. The first line leaves you with $one and $two both containing "dirlist". Of course.
The second line starts with a useless assignment. Both start by definition with "TTY" (a bit symbolic) as their direction; no value is changed by this assignment, and with variables as with filehandles, nothing is magically linked. Variable two is not affected by the following one=dirlist. Of course not.
Sombody here (6 years ago) suggested "point to" instead of "copy" or "duplicate", and then realized: that would be confusing too.
This duplication or pointer semantic is not even needed. Maybe it's the ampersand that needs more attention. The "value of" operator/token/whatever.
If - and only if - you are looking for a way to get a surprising job number on your console, then a "done" message plus as a bonus a file named "2", then you go:
ls 1>2& 2>/dev/null
It reads naturally as "copy"/"duplicate" 1 to 2, and then both together to null. But the idea is wrong, and also the syntax. (but no syntax error, it is valid)
The right way to plan it is to redirect any of the two to null, and then redirect the OTHER to the SAME place:
ls 1>/dev/null 2>&1
# or
ls 2>/dev/null 1>&2
(the leading "1" can be left away)
(OK the acc. A is not too long, but is too much of a list - or: very good visualisation, not so good explanation)
add a comment
|
DUPLICATION...
is important, but rather in the sense that it is the source of much confusion. It is really quite simple. This answer is just a "radical" illustration.
The accepted answer is good, but too long and it emphasizes "duplicatition".
The Q wisely ends with:
The use of the word duplication seems a little strange to me in
this context. Perhaps that is throwing me.
I use bash notation and define variables "one" and "two" as filehandles "1" and "2". The (output) redirection operator > is an assignment =. & and $ mean "value" of.
The man bash examples (with default "1" added)
ls 1>dirlist 2>&1 # both to dirlist
ls 2>&1 1>dirlist # 1 to dirlist, 2 stays on tty/screen
become:
one=dirlist two=$one
and
two=$one one=dirlist
And even this is non-automatic to me, and some others I guess. The first line leaves you with $one and $two both containing "dirlist". Of course.
The second line starts with a useless assignment. Both start by definition with "TTY" (a bit symbolic) as their direction; no value is changed by this assignment, and with variables as with filehandles, nothing is magically linked. Variable two is not affected by the following one=dirlist. Of course not.
Sombody here (6 years ago) suggested "point to" instead of "copy" or "duplicate", and then realized: that would be confusing too.
This duplication or pointer semantic is not even needed. Maybe it's the ampersand that needs more attention. The "value of" operator/token/whatever.
If - and only if - you are looking for a way to get a surprising job number on your console, then a "done" message plus as a bonus a file named "2", then you go:
ls 1>2& 2>/dev/null
It reads naturally as "copy"/"duplicate" 1 to 2, and then both together to null. But the idea is wrong, and also the syntax. (but no syntax error, it is valid)
The right way to plan it is to redirect any of the two to null, and then redirect the OTHER to the SAME place:
ls 1>/dev/null 2>&1
# or
ls 2>/dev/null 1>&2
(the leading "1" can be left away)
(OK the acc. A is not too long, but is too much of a list - or: very good visualisation, not so good explanation)
add a comment
|
DUPLICATION...
is important, but rather in the sense that it is the source of much confusion. It is really quite simple. This answer is just a "radical" illustration.
The accepted answer is good, but too long and it emphasizes "duplicatition".
The Q wisely ends with:
The use of the word duplication seems a little strange to me in
this context. Perhaps that is throwing me.
I use bash notation and define variables "one" and "two" as filehandles "1" and "2". The (output) redirection operator > is an assignment =. & and $ mean "value" of.
The man bash examples (with default "1" added)
ls 1>dirlist 2>&1 # both to dirlist
ls 2>&1 1>dirlist # 1 to dirlist, 2 stays on tty/screen
become:
one=dirlist two=$one
and
two=$one one=dirlist
And even this is non-automatic to me, and some others I guess. The first line leaves you with $one and $two both containing "dirlist". Of course.
The second line starts with a useless assignment. Both start by definition with "TTY" (a bit symbolic) as their direction; no value is changed by this assignment, and with variables as with filehandles, nothing is magically linked. Variable two is not affected by the following one=dirlist. Of course not.
Sombody here (6 years ago) suggested "point to" instead of "copy" or "duplicate", and then realized: that would be confusing too.
This duplication or pointer semantic is not even needed. Maybe it's the ampersand that needs more attention. The "value of" operator/token/whatever.
If - and only if - you are looking for a way to get a surprising job number on your console, then a "done" message plus as a bonus a file named "2", then you go:
ls 1>2& 2>/dev/null
It reads naturally as "copy"/"duplicate" 1 to 2, and then both together to null. But the idea is wrong, and also the syntax. (but no syntax error, it is valid)
The right way to plan it is to redirect any of the two to null, and then redirect the OTHER to the SAME place:
ls 1>/dev/null 2>&1
# or
ls 2>/dev/null 1>&2
(the leading "1" can be left away)
(OK the acc. A is not too long, but is too much of a list - or: very good visualisation, not so good explanation)
DUPLICATION...
is important, but rather in the sense that it is the source of much confusion. It is really quite simple. This answer is just a "radical" illustration.
The accepted answer is good, but too long and it emphasizes "duplicatition".
The Q wisely ends with:
The use of the word duplication seems a little strange to me in
this context. Perhaps that is throwing me.
I use bash notation and define variables "one" and "two" as filehandles "1" and "2". The (output) redirection operator > is an assignment =. & and $ mean "value" of.
The man bash examples (with default "1" added)
ls 1>dirlist 2>&1 # both to dirlist
ls 2>&1 1>dirlist # 1 to dirlist, 2 stays on tty/screen
become:
one=dirlist two=$one
and
two=$one one=dirlist
And even this is non-automatic to me, and some others I guess. The first line leaves you with $one and $two both containing "dirlist". Of course.
The second line starts with a useless assignment. Both start by definition with "TTY" (a bit symbolic) as their direction; no value is changed by this assignment, and with variables as with filehandles, nothing is magically linked. Variable two is not affected by the following one=dirlist. Of course not.
Sombody here (6 years ago) suggested "point to" instead of "copy" or "duplicate", and then realized: that would be confusing too.
This duplication or pointer semantic is not even needed. Maybe it's the ampersand that needs more attention. The "value of" operator/token/whatever.
If - and only if - you are looking for a way to get a surprising job number on your console, then a "done" message plus as a bonus a file named "2", then you go:
ls 1>2& 2>/dev/null
It reads naturally as "copy"/"duplicate" 1 to 2, and then both together to null. But the idea is wrong, and also the syntax. (but no syntax error, it is valid)
The right way to plan it is to redirect any of the two to null, and then redirect the OTHER to the SAME place:
ls 1>/dev/null 2>&1
# or
ls 2>/dev/null 1>&2
(the leading "1" can be left away)
(OK the acc. A is not too long, but is too much of a list - or: very good visualisation, not so good explanation)
answered 1 hour ago
rastafilerastafile
1435 bronze badges
1435 bronze badges
add a comment
|
add a comment
|
Thanks for contributing an answer to Unix & Linux Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f84279%2fis-this-a-typo-in-bash-manuals-redirection-section%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
See stackoverflow.com/q/14615653/1030675
– choroba
Jul 24 '13 at 15:48
1
A classic case of mixing up operations that are "by value" vs "by reference". When you duplicate a file descriptor it is a by value operation. In programming, after
a = 1; b = a; a = 2you expecta == 2 && b == 1to be true. The redirection2>&1is similar to theb = aassignment - it is by value, not by reference.2>&1does not wed file descriptor 2 to file descriptor 1 for all of eternity - they are still 2 distinct file descriptors, who happen to point to the same file.– jw013
Jul 30 '13 at 20:15