What happens when redirecting with 3>&1 1>/dev/null?Understanding process substitution in dashWhy is redirecting STDERR to /dev/null done this way?find with multiple -exec options; redirecting &>/dev/null for one exec command sends process to backgroundDifference between 2>&-, 2>/dev/null, |&, &>/dev/null and >/dev/null 2>&1Is this redirecting to /dev/null?Is >&- more efficient than >/dev/null?Redirect command output to /dev/nullRedirecting stdout and stderr still prints to stdoutIn the code “ exec >/dev/null; >/dev/null” what is happening under the hood?Redirection and piping for greppingWhat happens to file descriptors when the process is killed?

Where's this lookout in Nova Scotia?

Any advice on creating fictional locations in real places when writing historical fiction?

Why did David Cameron offer a referendum on the European Union?

Where is the logic in castrating fighters?

Why aren't space telescopes put in GEO?

Why are C64 games inconsistent with which joystick port they use?

What was the idiom for something that we take without a doubt?

Why is this Simple Puzzle impossible to solve?

What are these arcade games in Ghostbusters 1984?

A Riley Respite

Construct a word ladder

Which melee weapons have the Two-Handed property, but lack Heavy and Special?

Make 24 using exactly three 3s

Is Jon Snow the last of his House?

What is a really good book for complex variables?

Is the taxi route omitted in low visibility (LVP)?

My employer faked my resume to acquire projects

How to respond to an upset student?

Website returning plaintext password

What is a Centaur Thief's climbing speed?

Is it possible to play as a necromancer skeleton?

Inconsistent results from Wolfram Could

Is DateWithin30Days(Date 1, Date 2) an Apex Method?

Grammar Question Regarding "Are the" or "Is the" When Referring to Something that May or May not be Plural



What happens when redirecting with 3>&1 1>/dev/null?


Understanding process substitution in dashWhy is redirecting STDERR to /dev/null done this way?find with multiple -exec options; redirecting &>/dev/null for one exec command sends process to backgroundDifference between 2>&-, 2>/dev/null, |&, &>/dev/null and >/dev/null 2>&1Is this redirecting to /dev/null?Is >&- more efficient than >/dev/null?Redirect command output to /dev/nullRedirecting stdout and stderr still prints to stdoutIn the code “ exec >/dev/null; >/dev/null” what is happening under the hood?Redirection and piping for greppingWhat happens to file descriptors when the process is killed?






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;








0















I'm playing around with file descriptors to better grok them and I'm failing to understand the following.



$ grep "..." 3>&1 1>/dev/null
1
12
13
123
321
3


The above does not show in the shell any of the matches, this is obviously happening because I'm redirecting to /dev/null. What I don't understand is why 3>&1 doesn't make it so that I still see the output, since I made a copy of it in fd 3.



What am I missing?










share|improve this question







New contributor



exit_status is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.



















  • Why would grep output anything to fd 3?

    – muru
    May 20 at 0:21











  • Why wouldn't it? After all 1 is stdout and I'm duplicating it. Obviously I'm missing something, but I don't know what.

    – exit_status
    May 20 at 0:22











  • Because nothing tells it to? I don't see any reason why grep should magically start printing output on some random fd.

    – muru
    May 20 at 0:34











  • As for your duplicating fd 1, see askubuntu.com/a/860245

    – muru
    May 20 at 0:37






  • 1





    A fd does not "print" anything, but it's printed to. And grep is not printing anything to fd 3, so it doesn't matter if 3 points to the "screen" or elsewhere.

    – mosvy
    May 20 at 0:52


















0















I'm playing around with file descriptors to better grok them and I'm failing to understand the following.



$ grep "..." 3>&1 1>/dev/null
1
12
13
123
321
3


The above does not show in the shell any of the matches, this is obviously happening because I'm redirecting to /dev/null. What I don't understand is why 3>&1 doesn't make it so that I still see the output, since I made a copy of it in fd 3.



What am I missing?










share|improve this question







New contributor



exit_status is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.



















  • Why would grep output anything to fd 3?

    – muru
    May 20 at 0:21











  • Why wouldn't it? After all 1 is stdout and I'm duplicating it. Obviously I'm missing something, but I don't know what.

    – exit_status
    May 20 at 0:22











  • Because nothing tells it to? I don't see any reason why grep should magically start printing output on some random fd.

    – muru
    May 20 at 0:34











  • As for your duplicating fd 1, see askubuntu.com/a/860245

    – muru
    May 20 at 0:37






  • 1





    A fd does not "print" anything, but it's printed to. And grep is not printing anything to fd 3, so it doesn't matter if 3 points to the "screen" or elsewhere.

    – mosvy
    May 20 at 0:52














0












0








0


1






I'm playing around with file descriptors to better grok them and I'm failing to understand the following.



$ grep "..." 3>&1 1>/dev/null
1
12
13
123
321
3


The above does not show in the shell any of the matches, this is obviously happening because I'm redirecting to /dev/null. What I don't understand is why 3>&1 doesn't make it so that I still see the output, since I made a copy of it in fd 3.



What am I missing?










share|improve this question







New contributor



exit_status is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











I'm playing around with file descriptors to better grok them and I'm failing to understand the following.



$ grep "..." 3>&1 1>/dev/null
1
12
13
123
321
3


The above does not show in the shell any of the matches, this is obviously happening because I'm redirecting to /dev/null. What I don't understand is why 3>&1 doesn't make it so that I still see the output, since I made a copy of it in fd 3.



What am I missing?







io-redirection file-descriptors






share|improve this question







New contributor



exit_status is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.










share|improve this question







New contributor



exit_status is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.








share|improve this question




share|improve this question






New contributor



exit_status is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.








asked May 20 at 0:12









exit_statusexit_status

15718




15718




New contributor



exit_status is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.




New contributor




exit_status is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.














  • Why would grep output anything to fd 3?

    – muru
    May 20 at 0:21











  • Why wouldn't it? After all 1 is stdout and I'm duplicating it. Obviously I'm missing something, but I don't know what.

    – exit_status
    May 20 at 0:22











  • Because nothing tells it to? I don't see any reason why grep should magically start printing output on some random fd.

    – muru
    May 20 at 0:34











  • As for your duplicating fd 1, see askubuntu.com/a/860245

    – muru
    May 20 at 0:37






  • 1





    A fd does not "print" anything, but it's printed to. And grep is not printing anything to fd 3, so it doesn't matter if 3 points to the "screen" or elsewhere.

    – mosvy
    May 20 at 0:52


















  • Why would grep output anything to fd 3?

    – muru
    May 20 at 0:21











  • Why wouldn't it? After all 1 is stdout and I'm duplicating it. Obviously I'm missing something, but I don't know what.

    – exit_status
    May 20 at 0:22











  • Because nothing tells it to? I don't see any reason why grep should magically start printing output on some random fd.

    – muru
    May 20 at 0:34











  • As for your duplicating fd 1, see askubuntu.com/a/860245

    – muru
    May 20 at 0:37






  • 1





    A fd does not "print" anything, but it's printed to. And grep is not printing anything to fd 3, so it doesn't matter if 3 points to the "screen" or elsewhere.

    – mosvy
    May 20 at 0:52

















Why would grep output anything to fd 3?

– muru
May 20 at 0:21





Why would grep output anything to fd 3?

– muru
May 20 at 0:21













Why wouldn't it? After all 1 is stdout and I'm duplicating it. Obviously I'm missing something, but I don't know what.

– exit_status
May 20 at 0:22





Why wouldn't it? After all 1 is stdout and I'm duplicating it. Obviously I'm missing something, but I don't know what.

– exit_status
May 20 at 0:22













Because nothing tells it to? I don't see any reason why grep should magically start printing output on some random fd.

– muru
May 20 at 0:34





Because nothing tells it to? I don't see any reason why grep should magically start printing output on some random fd.

– muru
May 20 at 0:34













As for your duplicating fd 1, see askubuntu.com/a/860245

– muru
May 20 at 0:37





As for your duplicating fd 1, see askubuntu.com/a/860245

– muru
May 20 at 0:37




1




1





A fd does not "print" anything, but it's printed to. And grep is not printing anything to fd 3, so it doesn't matter if 3 points to the "screen" or elsewhere.

– mosvy
May 20 at 0:52






A fd does not "print" anything, but it's printed to. And grep is not printing anything to fd 3, so it doesn't matter if 3 points to the "screen" or elsewhere.

– mosvy
May 20 at 0:52











2 Answers
2






active

oldest

votes


















4














Your redirections do make FD 3 a copy of FD 1, so FD 3 will point to standard output and anything written to it will go to (by default) the TTY. You then redirect FD 1 to /dev/null, so anything written to FD 1 will be discarded. Because grep doesn't ever write to FD 3, nothing visible happens with it.



These happen in sequence: firstly a copy (dup2) of FD 1 is made to FD 3, so FD 3 henceforth points at what FD 1 currently points at, and secondly FD 1 is replaced by a pointer to /dev/null.



The end result is shown in the following diagram:



Diagram of redirections 3>&1 1>/dev/null



Standard error (in pink, FD 2) and FD 3 are to the TTY, and standard output is to /dev/null. FD 3 still points at the TTY because that's where FD 1 pointed when the copy was made. However, the grep command will not try to write anything to FD 3, so the copy never gets any use.



The "copying" is directional: after 3>&1 is processed, anything written to FD 3 will go to where FD 1 pointed at the time of processing. It doesn't "preserve" anything beyond that: if you subsequently redirect FD 1, anything written to it goes to the new place. What you've done is held on to the original destination of FD 1 in case you wanted to use it later. The only redirection that affects where grep's standard output ends up is the one 1>... that explicitly talks about where it goes.



If grep were to write to FD 3, it would appear in the terminal as expected. Because it only outputs to FD 1 normally, all of its actual output is being discarded.




We could make a grep outputting to FD 3 if we wanted:



( grep "..." >&3 )


That will take the regular output on FD 1 and point it at (the newly-created) FD 3 instead. This won't work if you run it directly, because FD 3 doesn't go anywhere, but we can incorporate it into something like this that makes use of it:



( grep "..." >&3 ) 3>&1 1>/dev/null


The command in parentheses outputs to FD 3. The redirections afterwards 1) point FD 3 (which now actually has content on it) at FD 1, and 2) then direct FD 1 away again (which has no effect). The end result is that you'll get the grep "..." output to standard output again, exactly where it would have been without all the fuss.



A practical use of this sort of redirection is something like



cmd 3>&1 1>&2 2>&3 3>&- | foo


which swaps FDs 1 and 2, using FD 3 as a temporary storage spot. It's also sometimes used for shell-script tricks, like faking process substitution in POSIX sh with ( cmd1 | ( cmd2 | ( main_command /dev/fd/3 /dev/fd/4 ) 4<&0 ) 3<&0 ). Otherwise, it's fairly rare that commands innately use any non-standard file descriptor by number (of course many open a file themselves and get one).






share|improve this answer

























  • I think I'm close to understanding it. Your answer seems to pass very close to the confusion I stated here. So grep by default does not write to fd 3, but it writes to fd 1 and fd 2, is that it? And I'm assuming every program is like this? How do I make it write to fd 3?

    – exit_status
    May 20 at 0:55












  • Get the source code, change it, and recompile. Very few programs use arbitrary file descriptors floating around, and if they did you'd hardly ever see it.

    – Michael Homer
    May 20 at 0:59






  • 1





    This will run a grep outputting to FD 3, and then re-send output from there to the TTY so you can see what it said, again redirecting FD 1 away (for no reason this time): ( grep x >&3 ) 3>&1 1>/dev/null

    – Michael Homer
    May 20 at 1:00



















1














You're redirecting file-descriptor 3 to file-descriptor 1, and you're redirecting 1 to /dev/null. You're not making a copy of anything.



The normal way to copy a file-descriptor is with tee.



Also, I don't know what your context is, but 3 isn't a built-in file descriptor. Presumably you'd already set it up to point to something?






share|improve this answer























  • I haven't pointed it to anything, the whole thing is in the example. I see here it being described as being duplicated (which I, for better or for worse, understood as making a copy). So I don't see how what you're saying does not contradict this.

    – exit_status
    May 20 at 0:23












  • In this source, while talking about 2>&1, the author says that "This one duplicates file descriptor 2 to be a copy of file descriptor 1".

    – exit_status
    May 20 at 0:29












  • I understand what you're saying now. You're correct: Fd 3 is now pointing to a copy of the thing fd 1 was pointing to before you redirected fd 1 to /dev/null. So if anything were written to fd 3, yes, it would get printed to the terminal. But you haven't sent anything to fd 3.

    – ShapeOfMatter
    May 20 at 0:49











  • But if I were to use 2 instead of 3, it would print to the terminal and I wouldn't have sent anything either (not that I know of, I mean). There's a difference here that escapes me.

    – exit_status
    May 20 at 0:52











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/3.0/"u003ecc by-sa 3.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
);



);






exit_status is a new contributor. Be nice, and check out our Code of Conduct.









draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f519859%2fwhat-happens-when-redirecting-with-31-1-dev-null%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes









4














Your redirections do make FD 3 a copy of FD 1, so FD 3 will point to standard output and anything written to it will go to (by default) the TTY. You then redirect FD 1 to /dev/null, so anything written to FD 1 will be discarded. Because grep doesn't ever write to FD 3, nothing visible happens with it.



These happen in sequence: firstly a copy (dup2) of FD 1 is made to FD 3, so FD 3 henceforth points at what FD 1 currently points at, and secondly FD 1 is replaced by a pointer to /dev/null.



The end result is shown in the following diagram:



Diagram of redirections 3>&1 1>/dev/null



Standard error (in pink, FD 2) and FD 3 are to the TTY, and standard output is to /dev/null. FD 3 still points at the TTY because that's where FD 1 pointed when the copy was made. However, the grep command will not try to write anything to FD 3, so the copy never gets any use.



The "copying" is directional: after 3>&1 is processed, anything written to FD 3 will go to where FD 1 pointed at the time of processing. It doesn't "preserve" anything beyond that: if you subsequently redirect FD 1, anything written to it goes to the new place. What you've done is held on to the original destination of FD 1 in case you wanted to use it later. The only redirection that affects where grep's standard output ends up is the one 1>... that explicitly talks about where it goes.



If grep were to write to FD 3, it would appear in the terminal as expected. Because it only outputs to FD 1 normally, all of its actual output is being discarded.




We could make a grep outputting to FD 3 if we wanted:



( grep "..." >&3 )


That will take the regular output on FD 1 and point it at (the newly-created) FD 3 instead. This won't work if you run it directly, because FD 3 doesn't go anywhere, but we can incorporate it into something like this that makes use of it:



( grep "..." >&3 ) 3>&1 1>/dev/null


The command in parentheses outputs to FD 3. The redirections afterwards 1) point FD 3 (which now actually has content on it) at FD 1, and 2) then direct FD 1 away again (which has no effect). The end result is that you'll get the grep "..." output to standard output again, exactly where it would have been without all the fuss.



A practical use of this sort of redirection is something like



cmd 3>&1 1>&2 2>&3 3>&- | foo


which swaps FDs 1 and 2, using FD 3 as a temporary storage spot. It's also sometimes used for shell-script tricks, like faking process substitution in POSIX sh with ( cmd1 | ( cmd2 | ( main_command /dev/fd/3 /dev/fd/4 ) 4<&0 ) 3<&0 ). Otherwise, it's fairly rare that commands innately use any non-standard file descriptor by number (of course many open a file themselves and get one).






share|improve this answer

























  • I think I'm close to understanding it. Your answer seems to pass very close to the confusion I stated here. So grep by default does not write to fd 3, but it writes to fd 1 and fd 2, is that it? And I'm assuming every program is like this? How do I make it write to fd 3?

    – exit_status
    May 20 at 0:55












  • Get the source code, change it, and recompile. Very few programs use arbitrary file descriptors floating around, and if they did you'd hardly ever see it.

    – Michael Homer
    May 20 at 0:59






  • 1





    This will run a grep outputting to FD 3, and then re-send output from there to the TTY so you can see what it said, again redirecting FD 1 away (for no reason this time): ( grep x >&3 ) 3>&1 1>/dev/null

    – Michael Homer
    May 20 at 1:00
















4














Your redirections do make FD 3 a copy of FD 1, so FD 3 will point to standard output and anything written to it will go to (by default) the TTY. You then redirect FD 1 to /dev/null, so anything written to FD 1 will be discarded. Because grep doesn't ever write to FD 3, nothing visible happens with it.



These happen in sequence: firstly a copy (dup2) of FD 1 is made to FD 3, so FD 3 henceforth points at what FD 1 currently points at, and secondly FD 1 is replaced by a pointer to /dev/null.



The end result is shown in the following diagram:



Diagram of redirections 3>&1 1>/dev/null



Standard error (in pink, FD 2) and FD 3 are to the TTY, and standard output is to /dev/null. FD 3 still points at the TTY because that's where FD 1 pointed when the copy was made. However, the grep command will not try to write anything to FD 3, so the copy never gets any use.



The "copying" is directional: after 3>&1 is processed, anything written to FD 3 will go to where FD 1 pointed at the time of processing. It doesn't "preserve" anything beyond that: if you subsequently redirect FD 1, anything written to it goes to the new place. What you've done is held on to the original destination of FD 1 in case you wanted to use it later. The only redirection that affects where grep's standard output ends up is the one 1>... that explicitly talks about where it goes.



If grep were to write to FD 3, it would appear in the terminal as expected. Because it only outputs to FD 1 normally, all of its actual output is being discarded.




We could make a grep outputting to FD 3 if we wanted:



( grep "..." >&3 )


That will take the regular output on FD 1 and point it at (the newly-created) FD 3 instead. This won't work if you run it directly, because FD 3 doesn't go anywhere, but we can incorporate it into something like this that makes use of it:



( grep "..." >&3 ) 3>&1 1>/dev/null


The command in parentheses outputs to FD 3. The redirections afterwards 1) point FD 3 (which now actually has content on it) at FD 1, and 2) then direct FD 1 away again (which has no effect). The end result is that you'll get the grep "..." output to standard output again, exactly where it would have been without all the fuss.



A practical use of this sort of redirection is something like



cmd 3>&1 1>&2 2>&3 3>&- | foo


which swaps FDs 1 and 2, using FD 3 as a temporary storage spot. It's also sometimes used for shell-script tricks, like faking process substitution in POSIX sh with ( cmd1 | ( cmd2 | ( main_command /dev/fd/3 /dev/fd/4 ) 4<&0 ) 3<&0 ). Otherwise, it's fairly rare that commands innately use any non-standard file descriptor by number (of course many open a file themselves and get one).






share|improve this answer

























  • I think I'm close to understanding it. Your answer seems to pass very close to the confusion I stated here. So grep by default does not write to fd 3, but it writes to fd 1 and fd 2, is that it? And I'm assuming every program is like this? How do I make it write to fd 3?

    – exit_status
    May 20 at 0:55












  • Get the source code, change it, and recompile. Very few programs use arbitrary file descriptors floating around, and if they did you'd hardly ever see it.

    – Michael Homer
    May 20 at 0:59






  • 1





    This will run a grep outputting to FD 3, and then re-send output from there to the TTY so you can see what it said, again redirecting FD 1 away (for no reason this time): ( grep x >&3 ) 3>&1 1>/dev/null

    – Michael Homer
    May 20 at 1:00














4












4








4







Your redirections do make FD 3 a copy of FD 1, so FD 3 will point to standard output and anything written to it will go to (by default) the TTY. You then redirect FD 1 to /dev/null, so anything written to FD 1 will be discarded. Because grep doesn't ever write to FD 3, nothing visible happens with it.



These happen in sequence: firstly a copy (dup2) of FD 1 is made to FD 3, so FD 3 henceforth points at what FD 1 currently points at, and secondly FD 1 is replaced by a pointer to /dev/null.



The end result is shown in the following diagram:



Diagram of redirections 3>&1 1>/dev/null



Standard error (in pink, FD 2) and FD 3 are to the TTY, and standard output is to /dev/null. FD 3 still points at the TTY because that's where FD 1 pointed when the copy was made. However, the grep command will not try to write anything to FD 3, so the copy never gets any use.



The "copying" is directional: after 3>&1 is processed, anything written to FD 3 will go to where FD 1 pointed at the time of processing. It doesn't "preserve" anything beyond that: if you subsequently redirect FD 1, anything written to it goes to the new place. What you've done is held on to the original destination of FD 1 in case you wanted to use it later. The only redirection that affects where grep's standard output ends up is the one 1>... that explicitly talks about where it goes.



If grep were to write to FD 3, it would appear in the terminal as expected. Because it only outputs to FD 1 normally, all of its actual output is being discarded.




We could make a grep outputting to FD 3 if we wanted:



( grep "..." >&3 )


That will take the regular output on FD 1 and point it at (the newly-created) FD 3 instead. This won't work if you run it directly, because FD 3 doesn't go anywhere, but we can incorporate it into something like this that makes use of it:



( grep "..." >&3 ) 3>&1 1>/dev/null


The command in parentheses outputs to FD 3. The redirections afterwards 1) point FD 3 (which now actually has content on it) at FD 1, and 2) then direct FD 1 away again (which has no effect). The end result is that you'll get the grep "..." output to standard output again, exactly where it would have been without all the fuss.



A practical use of this sort of redirection is something like



cmd 3>&1 1>&2 2>&3 3>&- | foo


which swaps FDs 1 and 2, using FD 3 as a temporary storage spot. It's also sometimes used for shell-script tricks, like faking process substitution in POSIX sh with ( cmd1 | ( cmd2 | ( main_command /dev/fd/3 /dev/fd/4 ) 4<&0 ) 3<&0 ). Otherwise, it's fairly rare that commands innately use any non-standard file descriptor by number (of course many open a file themselves and get one).






share|improve this answer















Your redirections do make FD 3 a copy of FD 1, so FD 3 will point to standard output and anything written to it will go to (by default) the TTY. You then redirect FD 1 to /dev/null, so anything written to FD 1 will be discarded. Because grep doesn't ever write to FD 3, nothing visible happens with it.



These happen in sequence: firstly a copy (dup2) of FD 1 is made to FD 3, so FD 3 henceforth points at what FD 1 currently points at, and secondly FD 1 is replaced by a pointer to /dev/null.



The end result is shown in the following diagram:



Diagram of redirections 3>&1 1>/dev/null



Standard error (in pink, FD 2) and FD 3 are to the TTY, and standard output is to /dev/null. FD 3 still points at the TTY because that's where FD 1 pointed when the copy was made. However, the grep command will not try to write anything to FD 3, so the copy never gets any use.



The "copying" is directional: after 3>&1 is processed, anything written to FD 3 will go to where FD 1 pointed at the time of processing. It doesn't "preserve" anything beyond that: if you subsequently redirect FD 1, anything written to it goes to the new place. What you've done is held on to the original destination of FD 1 in case you wanted to use it later. The only redirection that affects where grep's standard output ends up is the one 1>... that explicitly talks about where it goes.



If grep were to write to FD 3, it would appear in the terminal as expected. Because it only outputs to FD 1 normally, all of its actual output is being discarded.




We could make a grep outputting to FD 3 if we wanted:



( grep "..." >&3 )


That will take the regular output on FD 1 and point it at (the newly-created) FD 3 instead. This won't work if you run it directly, because FD 3 doesn't go anywhere, but we can incorporate it into something like this that makes use of it:



( grep "..." >&3 ) 3>&1 1>/dev/null


The command in parentheses outputs to FD 3. The redirections afterwards 1) point FD 3 (which now actually has content on it) at FD 1, and 2) then direct FD 1 away again (which has no effect). The end result is that you'll get the grep "..." output to standard output again, exactly where it would have been without all the fuss.



A practical use of this sort of redirection is something like



cmd 3>&1 1>&2 2>&3 3>&- | foo


which swaps FDs 1 and 2, using FD 3 as a temporary storage spot. It's also sometimes used for shell-script tricks, like faking process substitution in POSIX sh with ( cmd1 | ( cmd2 | ( main_command /dev/fd/3 /dev/fd/4 ) 4<&0 ) 3<&0 ). Otherwise, it's fairly rare that commands innately use any non-standard file descriptor by number (of course many open a file themselves and get one).







share|improve this answer














share|improve this answer



share|improve this answer








edited May 20 at 1:16

























answered May 20 at 0:52









Michael HomerMichael Homer

52.5k9145181




52.5k9145181












  • I think I'm close to understanding it. Your answer seems to pass very close to the confusion I stated here. So grep by default does not write to fd 3, but it writes to fd 1 and fd 2, is that it? And I'm assuming every program is like this? How do I make it write to fd 3?

    – exit_status
    May 20 at 0:55












  • Get the source code, change it, and recompile. Very few programs use arbitrary file descriptors floating around, and if they did you'd hardly ever see it.

    – Michael Homer
    May 20 at 0:59






  • 1





    This will run a grep outputting to FD 3, and then re-send output from there to the TTY so you can see what it said, again redirecting FD 1 away (for no reason this time): ( grep x >&3 ) 3>&1 1>/dev/null

    – Michael Homer
    May 20 at 1:00


















  • I think I'm close to understanding it. Your answer seems to pass very close to the confusion I stated here. So grep by default does not write to fd 3, but it writes to fd 1 and fd 2, is that it? And I'm assuming every program is like this? How do I make it write to fd 3?

    – exit_status
    May 20 at 0:55












  • Get the source code, change it, and recompile. Very few programs use arbitrary file descriptors floating around, and if they did you'd hardly ever see it.

    – Michael Homer
    May 20 at 0:59






  • 1





    This will run a grep outputting to FD 3, and then re-send output from there to the TTY so you can see what it said, again redirecting FD 1 away (for no reason this time): ( grep x >&3 ) 3>&1 1>/dev/null

    – Michael Homer
    May 20 at 1:00

















I think I'm close to understanding it. Your answer seems to pass very close to the confusion I stated here. So grep by default does not write to fd 3, but it writes to fd 1 and fd 2, is that it? And I'm assuming every program is like this? How do I make it write to fd 3?

– exit_status
May 20 at 0:55






I think I'm close to understanding it. Your answer seems to pass very close to the confusion I stated here. So grep by default does not write to fd 3, but it writes to fd 1 and fd 2, is that it? And I'm assuming every program is like this? How do I make it write to fd 3?

– exit_status
May 20 at 0:55














Get the source code, change it, and recompile. Very few programs use arbitrary file descriptors floating around, and if they did you'd hardly ever see it.

– Michael Homer
May 20 at 0:59





Get the source code, change it, and recompile. Very few programs use arbitrary file descriptors floating around, and if they did you'd hardly ever see it.

– Michael Homer
May 20 at 0:59




1




1





This will run a grep outputting to FD 3, and then re-send output from there to the TTY so you can see what it said, again redirecting FD 1 away (for no reason this time): ( grep x >&3 ) 3>&1 1>/dev/null

– Michael Homer
May 20 at 1:00






This will run a grep outputting to FD 3, and then re-send output from there to the TTY so you can see what it said, again redirecting FD 1 away (for no reason this time): ( grep x >&3 ) 3>&1 1>/dev/null

– Michael Homer
May 20 at 1:00














1














You're redirecting file-descriptor 3 to file-descriptor 1, and you're redirecting 1 to /dev/null. You're not making a copy of anything.



The normal way to copy a file-descriptor is with tee.



Also, I don't know what your context is, but 3 isn't a built-in file descriptor. Presumably you'd already set it up to point to something?






share|improve this answer























  • I haven't pointed it to anything, the whole thing is in the example. I see here it being described as being duplicated (which I, for better or for worse, understood as making a copy). So I don't see how what you're saying does not contradict this.

    – exit_status
    May 20 at 0:23












  • In this source, while talking about 2>&1, the author says that "This one duplicates file descriptor 2 to be a copy of file descriptor 1".

    – exit_status
    May 20 at 0:29












  • I understand what you're saying now. You're correct: Fd 3 is now pointing to a copy of the thing fd 1 was pointing to before you redirected fd 1 to /dev/null. So if anything were written to fd 3, yes, it would get printed to the terminal. But you haven't sent anything to fd 3.

    – ShapeOfMatter
    May 20 at 0:49











  • But if I were to use 2 instead of 3, it would print to the terminal and I wouldn't have sent anything either (not that I know of, I mean). There's a difference here that escapes me.

    – exit_status
    May 20 at 0:52















1














You're redirecting file-descriptor 3 to file-descriptor 1, and you're redirecting 1 to /dev/null. You're not making a copy of anything.



The normal way to copy a file-descriptor is with tee.



Also, I don't know what your context is, but 3 isn't a built-in file descriptor. Presumably you'd already set it up to point to something?






share|improve this answer























  • I haven't pointed it to anything, the whole thing is in the example. I see here it being described as being duplicated (which I, for better or for worse, understood as making a copy). So I don't see how what you're saying does not contradict this.

    – exit_status
    May 20 at 0:23












  • In this source, while talking about 2>&1, the author says that "This one duplicates file descriptor 2 to be a copy of file descriptor 1".

    – exit_status
    May 20 at 0:29












  • I understand what you're saying now. You're correct: Fd 3 is now pointing to a copy of the thing fd 1 was pointing to before you redirected fd 1 to /dev/null. So if anything were written to fd 3, yes, it would get printed to the terminal. But you haven't sent anything to fd 3.

    – ShapeOfMatter
    May 20 at 0:49











  • But if I were to use 2 instead of 3, it would print to the terminal and I wouldn't have sent anything either (not that I know of, I mean). There's a difference here that escapes me.

    – exit_status
    May 20 at 0:52













1












1








1







You're redirecting file-descriptor 3 to file-descriptor 1, and you're redirecting 1 to /dev/null. You're not making a copy of anything.



The normal way to copy a file-descriptor is with tee.



Also, I don't know what your context is, but 3 isn't a built-in file descriptor. Presumably you'd already set it up to point to something?






share|improve this answer













You're redirecting file-descriptor 3 to file-descriptor 1, and you're redirecting 1 to /dev/null. You're not making a copy of anything.



The normal way to copy a file-descriptor is with tee.



Also, I don't know what your context is, but 3 isn't a built-in file descriptor. Presumably you'd already set it up to point to something?







share|improve this answer












share|improve this answer



share|improve this answer










answered May 20 at 0:19









ShapeOfMatterShapeOfMatter

12615




12615












  • I haven't pointed it to anything, the whole thing is in the example. I see here it being described as being duplicated (which I, for better or for worse, understood as making a copy). So I don't see how what you're saying does not contradict this.

    – exit_status
    May 20 at 0:23












  • In this source, while talking about 2>&1, the author says that "This one duplicates file descriptor 2 to be a copy of file descriptor 1".

    – exit_status
    May 20 at 0:29












  • I understand what you're saying now. You're correct: Fd 3 is now pointing to a copy of the thing fd 1 was pointing to before you redirected fd 1 to /dev/null. So if anything were written to fd 3, yes, it would get printed to the terminal. But you haven't sent anything to fd 3.

    – ShapeOfMatter
    May 20 at 0:49











  • But if I were to use 2 instead of 3, it would print to the terminal and I wouldn't have sent anything either (not that I know of, I mean). There's a difference here that escapes me.

    – exit_status
    May 20 at 0:52

















  • I haven't pointed it to anything, the whole thing is in the example. I see here it being described as being duplicated (which I, for better or for worse, understood as making a copy). So I don't see how what you're saying does not contradict this.

    – exit_status
    May 20 at 0:23












  • In this source, while talking about 2>&1, the author says that "This one duplicates file descriptor 2 to be a copy of file descriptor 1".

    – exit_status
    May 20 at 0:29












  • I understand what you're saying now. You're correct: Fd 3 is now pointing to a copy of the thing fd 1 was pointing to before you redirected fd 1 to /dev/null. So if anything were written to fd 3, yes, it would get printed to the terminal. But you haven't sent anything to fd 3.

    – ShapeOfMatter
    May 20 at 0:49











  • But if I were to use 2 instead of 3, it would print to the terminal and I wouldn't have sent anything either (not that I know of, I mean). There's a difference here that escapes me.

    – exit_status
    May 20 at 0:52
















I haven't pointed it to anything, the whole thing is in the example. I see here it being described as being duplicated (which I, for better or for worse, understood as making a copy). So I don't see how what you're saying does not contradict this.

– exit_status
May 20 at 0:23






I haven't pointed it to anything, the whole thing is in the example. I see here it being described as being duplicated (which I, for better or for worse, understood as making a copy). So I don't see how what you're saying does not contradict this.

– exit_status
May 20 at 0:23














In this source, while talking about 2>&1, the author says that "This one duplicates file descriptor 2 to be a copy of file descriptor 1".

– exit_status
May 20 at 0:29






In this source, while talking about 2>&1, the author says that "This one duplicates file descriptor 2 to be a copy of file descriptor 1".

– exit_status
May 20 at 0:29














I understand what you're saying now. You're correct: Fd 3 is now pointing to a copy of the thing fd 1 was pointing to before you redirected fd 1 to /dev/null. So if anything were written to fd 3, yes, it would get printed to the terminal. But you haven't sent anything to fd 3.

– ShapeOfMatter
May 20 at 0:49





I understand what you're saying now. You're correct: Fd 3 is now pointing to a copy of the thing fd 1 was pointing to before you redirected fd 1 to /dev/null. So if anything were written to fd 3, yes, it would get printed to the terminal. But you haven't sent anything to fd 3.

– ShapeOfMatter
May 20 at 0:49













But if I were to use 2 instead of 3, it would print to the terminal and I wouldn't have sent anything either (not that I know of, I mean). There's a difference here that escapes me.

– exit_status
May 20 at 0:52





But if I were to use 2 instead of 3, it would print to the terminal and I wouldn't have sent anything either (not that I know of, I mean). There's a difference here that escapes me.

– exit_status
May 20 at 0:52










exit_status is a new contributor. Be nice, and check out our Code of Conduct.









draft saved

draft discarded


















exit_status is a new contributor. Be nice, and check out our Code of Conduct.












exit_status is a new contributor. Be nice, and check out our Code of Conduct.











exit_status is a new contributor. Be nice, and check out our Code of Conduct.














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.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f519859%2fwhat-happens-when-redirecting-with-31-1-dev-null%23new-answer', 'question_page');

);

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







Popular posts from this blog

Get product attribute by attribute group code in magento 2get product attribute by product attribute group in magento 2Magento 2 Log Bundle Product Data in List Page?How to get all product attribute of a attribute group of Default attribute set?Magento 2.1 Create a filter in the product grid by new attributeMagento 2 : Get Product Attribute values By GroupMagento 2 How to get all existing values for one attributeMagento 2 get custom attribute of a single product inside a pluginMagento 2.3 How to get all the Multi Source Inventory (MSI) locations collection in custom module?Magento2: how to develop rest API to get new productsGet product attribute by attribute group code ( [attribute_group_code] ) in magento 2

Category:9 (number) SubcategoriesMedia in category "9 (number)"Navigation menuUpload mediaGND ID: 4485639-8Library of Congress authority ID: sh85091979ReasonatorScholiaStatistics

Magento 2.3: How do i solve this, Not registered handle, on custom form?How can i rewrite TierPrice Block in Magento2magento 2 captcha not rendering if I override layout xmlmain.CRITICAL: Plugin class doesn't existMagento 2 : Problem while adding custom button order view page?Magento 2.2.5: Overriding Admin Controller sales/orderMagento 2.2.5: Add, Update and Delete existing products Custom OptionsMagento 2.3 : File Upload issue in UI Component FormMagento2 Not registered handleHow to configured Form Builder Js in my custom magento 2.3.0 module?Magento 2.3. How to create image upload field in an admin form