If I try to get the output (stdout) of a python program into a variable I do this:

set zpath (python something.py "$argv")

But if the program spawns a curses interface, it won't show.

The program displays a curses interface temporarily to select something, it exits the curses before the program ends. It prints something to stdout which is the useful data.

I read that I can I add 2>&1 >/dev/tty to the end of the command.

That does make the curses interface show but the output is not saved to the variable.

If I print something to test, it just prints it to the shell instead of into the variable.

How can I make the curses interface work, but also the stdout capture work?

I'm specially looking for a simple solution since the redirections to /dev/tty look messy,

and I need to make it work for different shells.

  • I would be surprised that a program forces some curses environment only for the selection of something. There must be somewhere some configuration file or some command line option enabling the user to bypass that phase by forcing the selection or offering a non-curses way to interact.
    – MC68020
    Commented Jun 15, 2022 at 8:58

1 Answer 1


I read that I can I add 2>&1 >/dev/tty to the end of the command.

This redirects stdout to the terminal (and stderr to where stdout originally went - the command substitution buffer).

If that shows the interface, and running it without redirections doesn't, that means the program uses stdout to display it.

That means, if

It prints something to stdout which is the useful data.

That output will also end up at the terminal.

I'm afraid if the program wants to use a tty on stdout to display its interface and then print the useful output to that same file descriptor, to stdout, then you can't redirect these two things separately. The shell can't separate them because they aren't separate.

What you would have to do is to modify the program so that it displays its interface on one file like /dev/tty, and print the useful output to another, like stdout.

This is also how fzf, which does open an interactive terminal interface and print something to stdout, operates - on unix it opens /dev/tty - see https://github.com/junegunn/fzf/blob/ef67a45702c01ff93e0ea99a51594c8160f66cc1/src/tui/light_unix.go#L50-L63 and https://github.com/junegunn/fzf/blob/b3ab6311c587e18ee202c5205afc658a33f2a23c/src/tui/light.go#L29

Or it could put the display on stdout and print the useful information on stderr - that would make that 2>&1 >/dev/tty trick work.


set zpath (python something.py "$argv")

In fish, you most likely do not want to quote that $argv - if it's set to multiple arguments you've now squashed them together into something nonsensical. It also won't help with e.g. spaces because fish does not perform word splitting like bash does. Once a variable has been set to X elements expanding it outside of quotes expands it to those X elements without splitting them apart again.

You must log in to answer this question.

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