0

I'm trying to figure out why the code below doesn't work, and gives me an error Bad file descriptor. It is sort of a follow-up to this question as applies to the script I'm currently working on.

Early on in the caller, exec 3>&1 is run, and nothing later explicitly changes it before the (generalized) function below is called like so:

exec 3>&1
...
string=$(GetString)

GetString looks like this:

GetString()
{
    4>&1 1>&3    #save pipe end and change output back to caller's
    controlvar=0

    while ((controlvar != 1))
    do    
        printf "some stuff for the interactive user\n"
        read -p "my prompt" variable
        if ValidationFunction $variable; controlvar=1;fi    #tests for valid input
    done
    exec 1>&4-    #change output back to pipe end
    echo $variable
}

I'm getting the Bad file descriptor error on the second to last line.

What's going on here? Note that I'm also not doing anything explicitly with fd/4 elsewhere in the script.

8
  • 1
    The exec 1>4- is incorrect, use exec 1>&4-. Commented Mar 18, 2016 at 22:36
  • I'm almost sure you don't need all of that... especially exec's... Can't you just pass file names? E.g. <command> << "$infile" >> "$outfile", or something like that. Commented Mar 18, 2016 at 22:40
  • 1
    @BryKKan A exec 1>4&- is still wrong, And I am leaning toward recommending the use of the simpler exec 4>&- to close file descriptor 4 but only after exec 1>&0 to recover stdout. Commented Mar 18, 2016 at 22:57
  • 2
    What is written in this answer is 1>&4-, well in fact, the equivalent >&4-. What you have written here is >4&-. If you fail to see the difference, well, nothing else to say. Commented Mar 19, 2016 at 0:26
  • 2
    And, you are missing an exec in the 4>&1 1>&3 line. Commented Mar 19, 2016 at 0:36

1 Answer 1

2

There are several problems with your question.

The line

4>&1 1>&3

Is missing an exec:

exec 4>&1 1>&3

And the line:

exec 1>4&-

Should read

exec 1>&4-

A simplified script should look as this:

GetString()
{
    exec 4>&1 1>&3    #save pipe end and change output back to caller's
    printf "some stuff for the interactive user\n"
    sleep 3    
    exec >&4-         #change output back to pipe end
    echo "test value"
}

exec 3>&1
string=$(GetString)
echo "final value <$string>"

This script makes sense.

Please edit the question to actually reproduce your problem.

1
  • Yes, my apologies for the repeated typo. The edited code is now exactly as it was on my terminal, and adding the foolishly forgotten exec fixed the issue. Thanks for your help. Commented Mar 19, 2016 at 0:51

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.