I am going to show an error window using zenity:

/usr/bin/zenity --error --text="my error message"

The error text to pass is obtained as output from another application. This output may contain quotes, backslashes and other special symbols which could prevent zenity to start correctly.

/usr/bin/zenity --error --text=$(/usr/bin/some-application)
### e.g. output of /usr/bin/some/application is: failed to "' \perform
### so here will be an error

What is the easiest way to normalize such output before passing to zenity? /bin/tr I suppose? But I'd like to show the original message not modified.

  • 1
    Try quoting the expansion, i.e. --text="$( ... )". Quotes and backslashes that result from expansions should not have any special meaning or side effects. My guess is whitespace in your command output is causing the output to be split into multiple words. In that case, zenity would see a --text=<first word> and the rest of the output as normal arguments. Quoting with " prevents word splitting. – jw013 Apr 30 '12 at 20:07

I can't find this in the documentation, but Zenity appears to do backslash expansion on the string passed to --text, which is then interpreted as Pango Text Attribute Markup, an HTML-like format. (Thanks to manatwork for pointing this out.)

First, you need to put double quotes around the command substitution, to avoid expansions performed by the shell. This is general in shell programming: always put double quotes around variable substitutions and command substitutions (i.e. "$foo" and "$(foo)"), unless you know why you can and must leave them off.

Second, you need to double all the backslashes coming from the application, and to replace the characters . You can do this with sed.

/usr/bin/zenity --error --text \
    "$(/usr/bin/some-application |
       sed -e 's/\\/\\\\/g' -e 's/&/\&amp;/g' -e 's/</\&lt;/g' -e 's/>/\&gt;/g')"

Strictly speaking, this does not reproduce the output from the application perfectly: if there are multiple newlines at the end of its output, they will be stripped. The stripping is performed by the shell's command substitution construct, so to avoid this, you need to ensure that the substituted command's output does not end in a newline.
    output="$(/usr/bin/some-application | sed 's/\\/\\\\/g'; echo a)"
    /usr/bin/zenity --error --text="${output%a}"
The difference won't be very visible in the dialog box though.

  • 1
    Actually Zenity supports Pango Text Attribute Markup so literal < and > should be transformed into HTML character entities. – manatwork May 1 '12 at 13:19
  • @manatwork Thanks! I've added entity escaping to the sed snippet. – Gilles May 1 '12 at 17:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.