9

I have scripts I run that write out a text file, then open it in an editor. If I open a terminal emulator window in my desktop session and run the script, I'd like the editor to be a graphical one such as gedit. But, if I'm logged in through ConnectBot on my phone or similar (no desktop session), I'd like the editor to be nano.

Currently I have to maintain 2 different scripts, identical except for the last step (or let the graphical one run, error off, then manually open the file in nano). Having two mostly identical scripts is inefficient from a maintenance standpoint.

Can a script detect which of these situations I'm in, and open the correct editor?

(I have found ways for a script to detect whether it's running in a terminal emulator window or by being double-clicked, but not yet found a way to detect if the window is running in a desktop...I don't think I know the correct terminology to google for)

2
  • 6
    If your script is for use by other people you should use the program specified by $EDITOR by default instead of nano, and fallback on nano if it is not set.
    – Bakuriu
    May 21, 2018 at 17:42
  • Thanks, great advice, and it's great to hear what is good practice. Just me though. May 21, 2018 at 17:42

3 Answers 3

12

You can use the environment variable $DISPLAY as trigger within a if condition. Usually when this variable has a value you are able to run graphical applications.

Here is a example:

if [[ -z $DISPLAY ]]
then
    nano
else
    gedit
fi

The operator -z will return true when the envvar $DISPLAY is empty and your script will run nano, in all other cases it will run gedit.


According to the this comment of @vurp0:

On most modern Wayland desktops (like the default desktop in Fedora and Ubuntu), $DISPLAY is still set due to backwards compatibility (through XWayland), but for a more robust script it would be good to test for both $DISPLAY and $WAYLAND_DISPLAY to be sure.

I would suggest to modify the test expression in the following way:

[[ -z ${DISPLAY}${WAYLAND_DISPLAY} ]]

Thus, the values of the two variables will be concatenated into a common string, which will be processed by the operator -z.


References:

1
  • 1
    Or for explicit logic: [[ -z ${DISPLAY} && -z ${WAYLAND_DISPLAY} ]] May 21, 2018 at 21:00
7

Typically virtual terminals use /dev/pts pseudo-terminals. So, based on the output of tty command, we can build a simple case statement to handle opening particular editor:

case "$(tty)" in ; "/dev/pts"*) nano ;; "/dev/tty"*) gedit ;; ;esac

Or formatted more nicely:

case "$(tty)" in
    "/dev/pts"*) gedit ;; 
    "/dev/tty"*) nano ;;
    *) echo "Not suitable tty" > /dev/stderr ;;
esac

Compared to using environment variables, this is slightly more reliable and considering it uses case statement with tty command slightly more portable. What probably would be best is to combine both, with extra testing, such as "/dev/tty"*) [ -n "$DISPLAY" ] && gedit ;;

2
  • Isn't this the wrong way around? On my Ctrl+Alt+F1 console, tty gives /dev/tty1, whereas gnome-terminal (first tab) gives /dev/pts/0. May 29, 2018 at 11:25
  • @PaddyLandau Yes, gedit should be in /dev/pts* case. I switched them around while error testing in tty and ended up copying it here without switching back. Thanks, edited already. May 29, 2018 at 14:40
3

This is what I've been using:

# $TERM variable may be missing when called via desktop shortcut
CurrentTERM=$(env | grep TERM)
if [[ $CurrentTERM == "" ]] ; then
    notify-send --urgency=critical "$0 cannot be run from GUI without TERM environment variable."
    exit 1
fi

The reason for this code was this question: Desktop shortcut to Bash script crashes and burns

You can modify it to look like this:

# $TERM variable may be missing when called via desktop shortcut
CurrentTERM=$(env | grep TERM)
if [[ $CurrentTERM == "" ]] ; then
    nano ...
else
    gedit ...
fi

You must log in to answer this question.

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