3

I'm trying to suppress GtkDialog warnings in zenity and yad:

$ zenity --error --text hello
Gtk-Message: GtkDialog mapped without a transient parent. This is discouraged.

Error redirection and filtering works:

$ zenity --error --text hello 2> >(grep -v GtkDialog >&2)

YEAH... Annoying warning message disappears!!

This can be placed in ~/.bashrc for development work as answered here:

and here:

When creating a script for others to use though, you don't want the burden of them changing their ~/.bashrc.


I'm having trouble creating a typing shortcut for: 2> >(grep -v GtkDialog >&2) to be used inside script.

For many reasons variable assignment GTK_SPAM="2> >(grep -v GtkDialog >&2)" followed later by variable usage "$GTK_SPAM" doesn't work.

alias zenity="zenity 2> >(grep -v GtkDialog >&2)" before calling script works but, I can't use this within a script.

Using an array to hold the typing shortcut isn't working:

$ aGtkSpam=(2\> \>\(grep -v GtkDialog \>\&2\))

$ DumpArray "${aGtkSpam[@]}"
Array Elements:
0: 2>
1: >(grep
2: -v
3: GtkDialog
4: >&2)

$ zenity --error --text hello "${aGtkSpam[@]}"
This option is not available. Please see --help for all possible usages.

$ yad --text hello 2> >(grep -v GtkDialog >&2)

$ yad --text hello "${aGtkSpam[@]}"
Gtk-Message: GtkDialog mapped without a transient parent. This is discouraged.

I found many excellent generic answers on word-splitting and parameters which should solve my problem but a specific syntax eludes me.

Any clues?

dessert
  • 39,392
  • 12
  • 115
  • 163
WinEunuuchs2Unix
  • 99,709
  • 34
  • 237
  • 401
  • 2
    Can't you just redirect stderr for the duration of the script using `exec`? Something like `exec 2> >(grep -v GtkDialog >&2)` – steeldriver May 17 '19 at 17:16
  • @steeldriver you mean use that command on second line after the `#!/bin/bash`? – WinEunuuchs2Unix May 17 '19 at 17:21
  • anywhere before where you want to start filtering the stream - doesn't have to be right after the shebang – steeldriver May 17 '19 at 17:24
  • steeldriver's suggestion is good and works in interactive shells as well. @steeldriver I would recommend making an answer out of that. – Sergiy Kolodyazhnyy May 17 '19 at 17:32
  • Array may have to be unquoted for this to work – Sergiy Kolodyazhnyy May 17 '19 at 17:33
  • @steeldriver Your idea is an elegant solution and turns my question into an XY problem. It also fixes both `yad` and `zenity` plus other apps I image all at once. Please post an answer for me to accept. – WinEunuuchs2Unix May 17 '19 at 17:36
  • @WinEunuuchs2Unix I've posted an answer but note that it is largely untested - please use with caution – steeldriver May 17 '19 at 18:02
  • @dessert It's a lot of awkward typing to remember and not as readable as "$NoSpamMsg" every time `yad` is used in your script. – WinEunuuchs2Unix May 17 '19 at 19:33
  • @SergiyKolodyazhnyy removing the quotes around `${aGtkSpam[@]}` did not help but it was a good idea. Jarno pointed that out a couple of years ago on a different script and it worked then. See my comment below SteelDriver's answer for my more targeted solution that allows other GtkDialog errors to flow through. – WinEunuuchs2Unix May 17 '19 at 23:46

3 Answers3

8

I don't think syntax alone can help you here - because of the order in which the shell sets up redirections and expands variables. To give a very simple illustration:

$ arr=( ">" "/dev/null" )
$ set -x
$ echo foo "${arr[@]}"
+ echo foo '>' /dev/null
foo > /dev/null

i.e. everything has been expanded "correctly", but > /dev/null has simply become a list of string arguments passed to echo.

You could force evaluation using eval:

$ eval echo foo "${arr[@]}"
+ eval echo foo '>' /dev/null
++ echo foo

but really it would be better to redirect the stream for the duration of your script using exec:

exec 2> >(grep -v GtkDialog >&2)

or, if you want to be able to turn the filter off before the end of the script, then based on After using exec 1>file, how can I stop this redirection of the STDOUT to file and restore the normal operation of STDOUT? it should be possible to do

exec 3>&2 2> >(grep -v GtkDialog >&2)

and then later

exec 2>&3 3>&-

to recover the duplicated stream.

steeldriver
  • 131,985
  • 21
  • 239
  • 326
  • 1
    I haven't tested everything but `exec 2> >(grep -v 'GtkDialog mapped without a transient parent' >&2)` in script before using `yad` works fine as far as I can tell. – WinEunuuchs2Unix May 17 '19 at 18:41
7

You can define and use aliases in your script if you set the expand_aliases shell option, e.g.:

#!/bin/bash
shopt -s expand_aliases
alias zenity='zenity 2> >(grep -v GtkDialog >&2)'
…

Now every zenity line behaves as if 2> >(grep -v GtkDialog >&2) were added and you can disable this behaviour as usual by prepending a backslash or command:

\zenity        # and
command zenity

both ignore the alias.

Further reading

dessert
  • 39,392
  • 12
  • 115
  • 163
  • Although upvoting your answer I'm still using SteelDriver's answer for the time-being. Your answer did inspire me to use `shopt -u expand_aliases` so aliases cannot create unstable environment for my script. In other words, turn off all the user's aliases so the script doesn't behave erratically. – WinEunuuchs2Unix May 17 '19 at 23:42
  • @WinEunuuchs2Unix That’s not necessary, as “Aliases are not expanded when the shell is not interactive” – if you didn’t set the option before in your script it’s no use. – dessert May 18 '19 at 07:17
6

You can use function in the script. zenity and yad have useful info in stdout, so I suggest to redirect just stderr to /dev/null

#/bin/bash

zen_nospam() {
  zenity "$@" 2&>1 >(grep -v GtkDialog >&2)
}

zen_nospam --error --text hello

btw function can be defined in .bashrc if needed in command line, not script

LeonidMew
  • 2,724
  • 1
  • 20
  • 38