Inspired by this forum post, I ran this command at a Bash prompt:

echo -e '\e]4;40;?\a'

Which outputs:

# 4;rgb:8b8b/cdcd/0000

But the weird thing is, the output somehow becomes my prompt's next command, instead of being printed above my prompt.

I'd like to save the "4;rgb:8b8b/cdcd/0000" text in a variable, but to my surprise, the same problem happens when I do this:

output=$(echo -e '\e]4;30;?\a')
echo "$output"

Same for this:

echo -e '\e]4;30;?\a'   |   awk  -F ":"  ' { print $1 } '

How can I save the "4;rgb:8b8b/cdcd/0000" output into a variable, or pipe it?

Thanks for any help!


Edit: Thanks for the reply! But, the same problem happens with this, too:

out=`eval "echo -e '\e]4;40;?\a'"`; echo $out


I then tried creating a substring of the $out variable, but, this printed a blank line instead of "4;rgb":

substring=${out:0:5}; echo "$substring"


I also tried this:

out=`eval "echo -e '\e]4;40;?\a'"`; echo $out |  awk  -F ":"  ' { print $1 } '

awk responds with a blank line (instead of "4;rgb"), then "4;rgb:8b8b/cdcd/0000" appears on my prompt as the next command.


Rather than add tools, you can use the ones that you are likely to have (and in the process, learn something). If you want to use Puppy Linux effectively, this would be a good thing.

Here is a quick example using just the shell, cat, printf, stty and tty (all part of GNU CoreUtils, although the example avoids using nonportable features which those programs provide):

# $Id: osc4-demo,v 1.2 2016/04/03 12:50:20 tom Exp $
# A simple demo for retrieving a color using xterm's OSC 4 control

osc4_demo() {
        old=$(stty -g);
        stty raw -echo min 0 time 2;
        printf '\033]4;%d;?\007' "$1" >$(tty);
        cat $(tty);
        stty $old
    echo "asked $1, result: $(echo "$result" | cat -v)"

for code in "$@"
    osc4_demo $code

The script sets the result variable and echoes it in printable form. For example:

$ osc4-demo 4 44 144 244
asked 4, result: ^[]4;4;rgb:0000/0000/eeee^G
asked 44, result: ^[]4;44;rgb:0000/d7d7/d7d7^G
asked 144, result: ^[]4;144;rgb:afaf/afaf/8787^G
asked 244, result: ^[]4;244;rgb:8080/8080/8080^G

It works by temporarily changing the terminal to raw mode, with the ability to read values back without a terminating newline. That is essentially what the tools would do.

Because the script sends/receives to/from the actual tty, you can redirect the result to a file. It uses the -v option of cat to make the result readable (though the actual variable controls the control characters).

I considered adding

exec < /dev/tty

to improve this, based on other scripts for xterm (see for example Using exec in the Advanced Bash-Scripting Guide), but found that did not help with Debian's dash.

The multi-line expression can of course be folded into a single line for those who insist on that form, with the usual loss of clarity.

Further reading:

  • A belated thanks for this very clever and educational answer! Somehow I didn't see it until today. Anyway, I finally tried the above script, and it works great in Lighthouse 64 Puppy Linux 6.02 Beta 2! lhpup.org I'm so surprised and pleased it's possible to do that without having to install any software I didn't already have. – Apollia Jun 13 '18 at 19:49
  • Also, huge thanks for your wonderful work on so many awesome tools! Lynx is still one of my favorite web browsers ever - I used to use it all the time back in the 1990's when my only internet access was a free text-only dialup account with a local free-net. en.wikipedia.org/wiki/Free-Net – Apollia Jun 13 '18 at 19:50

The string you get 4;rgb:8b8b/cdcd/0000 is not really the output of the echo command but a side effect of the echoed string being sent to your terminal emulator and the latter reacting to it by outputting these characters, just like if you typed them.

The shell is unaware of it and that's the reason why attempting to capture the output results in empty strings.

Here is a way to achieve what you want:

script -qc "echo -e '\e]4;40;?\a';read foo" /tmp/foo
out=$(tail -1 /tmp/foo)

Here are some explanations about it:.The script command is capturing everything that is displayed on your screen, the read foo one is there to prevent the script command to finish before the terminal emulator has output the string you want to get. The tail -1 command is stripping the unwanted lines generated by the script command.

  • Thanks, this worked great! In Puppy Linux, I didn't have the "script" command available by default, but I was able to compile it from source, which I downloaded here: kernel.org/pub/linux/utils/util-linux – Apollia Apr 2 '16 at 9:37

You can also use xtermcontrol --get-colorN for the first 16 colors. Alas it doesn't support the entire 256 color palette.

  • Thanks! xtermcontrol definitely looks useful in many ways! I don't yet have xtermcontrol in Puppy Linux, but, happily, I can download it here: thrysoee.dk/xtermcontrol – Apollia Apr 2 '16 at 9:43

Try with eval (a good post about eval can be found here)

out=`eval "echo -e '\e]4;40;?\a'"`; echo $out

The contents are stored in $out, they are printed only if I include echo $out

  • Thanks! That didn't work as I hoped (as I explained in an update of my original post). But, I hadn't thought of trying eval, so thanks for the idea, and the interesting link about eval! – Apollia Apr 2 '16 at 9:57

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.