I have a pretty good idea how file descriptors work in Bash to accomplish I/O redirection in a practical level, but there is a case I found online (https://linuxcommand.org/lc3_adv_dialog.php, under "Method 2: Using Command Substitution and Redirection") that I do not fully understand why it is being used.

There is an execution that requires to redirect the stderr to stdout in order to capture the errors in a command substitution and that makes perfect sense to me, but there is an extra redirection that is done that I feel requires knowledge of how file descriptors work in a lower level. Pseudocode:

exec 3>&1
var=$(cmd -options ... 2>&1 1>&3)
exec 3>&-

What is the point of making a backup of stdout and redirect stdout to the location it was already pointing to? stdout was never altered besides now receiving the contents of stderr.

My best guess is that fd 3 contains the original state of stdout and redirecting fd 1 to fd 3 returns it to its original state before having fd 2 redirected to it? I would love some insight or reading materials.

  • Could you provide a reference to where you saw this? It would be useful for context.
    – Kusalananda
    Dec 2, 2020 at 16:34
  • linuxcommand.org/lc3_adv_dialog.php Under "Method 2: Use Command Substitution and Redirection"
    – AnthonyBB
    Dec 2, 2020 at 16:42
  • 2
    As written, this does just sent stdout and stderr to the same fd1. But the command substitution does a further redirection of its own -- it redirects stdout within the $(..) so it is collected and assigned to the variable (or arg). So the fd1 assigned to the command being substituted is not the same one as in the execs. Dec 2, 2020 at 16:46
  • @Paul_Pedant If I understand what you are saying correctly, does that mean then that the fd1 of the command substitution is being redirected to the stdout of the parent process of the command substitution? Allowing then the stdout of the $(...) to print to terminal (in this case)?
    – AnthonyBB
    Dec 2, 2020 at 16:56
  • 2
    You aren't showing the command substitution in your example, and you have skipped the discussion about "dialog needs standard output to point to the terminal so that it can display the input box" that is mentioned in the original text.
    – Kusalananda
    Dec 2, 2020 at 17:04

1 Answer 1


In the form you wrote initially, where the command is simply cmd -options ... 2>&1 1>&3, this has little sense, as effectively both stderr and stdout are redirected to stdout. So 1>&3 is unneeded.

But the example you referred to is a different case. What we have there is variable=$(cmd -options ... 2>&1 1>&3). The $(command) construct redirects stdout of command by itself, so that it can be captured and placed in a variable. So in this case first stderr of command is redirected to already redirected stdout (2>&1), ie. will be placed in the variable, and after this stdout of command is redirected to original stdout before redirection, kept in descriptor 3 (1>&3). The effect is that stderr of the command will be placed in the variable and stdout will be displayed normally - kinda opposite of "regular" variable=$(command) case where stdout is placed in the variable and stderr displayed. It is pretty well explained on the very same page you are linking to:

At first glance, the redirection may seem nonsensical. First, we duplicate file descriptor 1 (stdout) to descriptor 3 using exec (this was covered in More Redirection) to create a backup copy of descriptor 1.

The next step is to perform a command substitution and assign the output of a the dialog command to the variable result. The command includes redirections of descriptor 2 (stderr) to be the duplicate of descriptor 1 and lastly, descriptor 1 is restored to its original value by duplicating descriptor 3 which contains the backup copy. What might not be immediately apparent is why the last redirection is needed. Inside the subshell, standard output (descriptor 1) does not point to the controlling terminal. Rather, it is pointing to a pipe that will deliver its contents to the variable result. Since dialog needs standard output to point to the terminal so that it can display the input box, we have to redirect standard error to standard output (so that the output from dialog ends up in the result variable), then redirect standard output back to the controlling terminal.

  • 1
    I have been reading that explanation so many times and it was not clicking at all, which is why I asked the question to see if someone could explain it differently enough that it would make sense.
    – AnthonyBB
    Dec 2, 2020 at 17:07
  • @AnthonyBB And has that been achieved? Dec 2, 2020 at 18:46
  • @Paul_Pedant It has. Your comment and Kusalananda's made me realize that I was not paying attention to the key elements that made this case work. The accepted answer supplemented what you brought up. After doing research on processes and subshells this all makes sense now. Thank you!
    – AnthonyBB
    Dec 2, 2020 at 20:47

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .