stant
stant

Reputation: 26

sh/bash command substitution freezes script

There is simple one-line script:

myvar=`nano`

If I run this with bash or sh it freezes current terminal session and editor will not be shown. I tried other interactive programs and different operating systems (Ubuntu, FreeBSD), results are always the same. I think it's because those programs are ignoring signals, but I don't understand why they can't start in such a way.

I need this method because I want to release the function that captures text input from user and return it to caller. For example:

function read_text()
{
   local tempfile=`mktemp`
   nano $tempfile
   cat $tempfile
   rm $tempfile
}

echo "Press ENTER to input your comment." 
read # ENTER
comment=`read_text`

UPDATE:

Thanks to tripleee for directing me to the reason of this problem. I found simple solution. It is to redirect problem to current terminal line.

There is simple one-line script:

myvar=`nano > $(tty)`

Full example:

read_text()
{
   local tempfile=`mktemp`
   nano $tempfile > `tty`
   cat $tempfile
   rm $tempfile
}
comment=`read_text`
echo $comment

Upvotes: 0

Views: 1208

Answers (1)

tripleee
tripleee

Reputation: 189387

You cannot run interactive commands inside backircks, because the backticks will prevent interactive input and output between the program and your terminal.

A reasonable refactoring of your problem would be to handle the temp file in the caller, and do away with the function; or at least, reduce the scope of the function.

local tempfile=$(mktemp)
${VISUAL-nano} "$tempfile"
comment=$(cat "$tempfile")
rm "$tempfile"

Notice also how this code uses $VISUAL and falls back to nano only if this standard variable is unset.

For most real-world scenarios, if the input task is significant enough to warrant the use of an external editor, you will probably be better off passing around the temporary file (use a trap to remove it at the very end of the script) instead of grabbing its contents into a shell variable.

# At the beginning of your script
tmpdir=$(mktemp -d -t yourscript.XXXXXXXX)
trap 'rm -rf "$tmpdir"' 0
trap 'exit 127' 1 2 3 5 15

:

echo '# Enter your comment here' >"$tmpdir"/comment
${VISUAL-nano} "$tmpdir"/comment

As you can see, this turns out simple enough that you don't really need to encapsulate it into a separate function.

Upvotes: 1

Related Questions