What's the purpose of these redirections and file descriptors? What's the purpose of these redirections and file descriptors? bash bash

What's the purpose of these redirections and file descriptors?


Normally dialog displays its dialog box to the user through stdout, which is file descriptor 1, reads the user's keystrokes from stdin, which is file descriptor 0, and outputs the values filled in by the user to stderr, which is file descriptor 2.

The reason for bringing in an extra file descriptor is to read the values through $(command…) substitution (same as backquotes). Command substitution takes whatever the inner command (in this case, dialog…) sent to its stdout and fills it into the outer command (in this case, VALUES=…).

The 2>&1 redirection makes dialog send the field values to its stdout, where they will be captured into VALUES. So, dialog needs a different file descriptor to display the dialog box to the user. The exec 3>&1 duplicates the original stdout file descriptor. That is, after that command, file descriptor 3 and file descriptor 1 refer to the same file—the original stdout. The 1>&3 redirection makes dialog display its dialog to that original stdout.

To put that another way, the reason for bringing in file descriptor 3 is to temporarily "save" stdout.


The breakdown is simple:

exec 3>&1

Anything written to file descriptor 3 will go the same place as file descriptor 1, standard output.

VALUES=$(command ...arguments... 2>&1 1>&3)

Here, anything written to file descriptor 2, standard error, will go the same place as file descriptor 1, standard output. However, the definition of standard output is then changed so that anything written to standard output goes to the same place as file descriptor 3. This is inside a command substitution $(...) operation, so the standard output is normally captured in a file. It means that the variable VALUES gets to hold whatever the command writes to standard error, while the original standard output gets whatever the command writes to standard output.

Finally:

exec 3>&-

closes file descriptor 3; attempts to write to it will fail from here on.

Your simulation of the command should be:

exec 3>&1variable=$(ls 2>&1 1>&3)exec 3>&-

This would capture any errors from ls in $variable, while allowing you to see whatever ls wrote on standard output. You don't see this sort of thing done normally because the requirements are a bit unusual.