NOTE: a newline appears but od -c doesn't display it.

My music player's status command (quodlibet --status | od -c) has three states, and I'm trying to write a conditional based on that output. The outputs from that command are like this (may differ depending on the configuration).

  1. I think this is printing to stderr because od -c doesn't display properly, even though it does for the other commands.

    not-running
    0000000
    
  2. paused

    0000000   p   a   u   s   e   d       P   a   n   e   d   B   r   o   w
    0000020   s   e   r       1   .   0   0   0       s   h   u   f   f   l
    0000040   e       o   n       0   .   2   2   8  \n
    0000053
    
  3. playing

    0000000   p   l   a   y   i   n   g       P   a   n   e   d   B   r   o
    0000020   w   s   e   r       1   .   0   0   0       s   h   u   f   f
    0000040   l   e       o   n       0   .   2   3   2  \n
    0000054
    

My goal is to remove everything except "not-running", "paused", or "playing" and use that in a conditional, like this:

#!/bin/bash

status=$(quodlibet --status | awk '{split($0,m," "); printf "%s",m[1]}' | tr -d '\000\007\010\n')
if [ "$status" = "playing" ]; then
  quodlibet --print-playing '<artist>: <title>' | cut -c1-45
else
  echo -n "$status"
fi

In the case where the player isn't running though this always prints a newline in the terminal after "not-running." Even if I do something like this

echo -n "$(quodlibet --print-playing '<artist>: <title>' | cut -c1-45)"

If I pipe that output to od -c, I get the same

not-running
0000000

which isn't right. The newline doesn't show up, but its their in the terminal.

Questions

  • What's causing this?
  • Is the command printing to standard error when the program isn't running?
  • How can I determine this?
up vote 6 down vote accepted

Couple of ways to approach this.

  1. merge streams

    You could by pass determining the difference all together and simply merge STDERR and STDOUT.

    Example

    quodlibet --status 2>&1 | ...
    
  2. use grep

    You could chop the output down by using the -o & -E switches to grep.

    Example

    $ echo "...blah not-running blah..." | grep -Eo "not-running|paused|playing"
    not-running
    
    $ echo "...blah paused blah..." | grep -Eo "not-running|paused|playing"
    paused
    
    $ echo "...blah playing blah..." | grep -Eo "not-running|paused|playing"
    playing
    

    This will cut everything out except for the strings that match the regex argument to grep.

  3. determine the stream's type

    You can use the -t switch to determine the type of the file descriptor stream.

    excerpt from Bash man page

    -t fd True if file descriptor fd is open and refers to a terminal.

    where fd is one of:

    0: stdin
    1: stdout
    2: stderr

    Example

    This detects if the output is coming from STDOUT.

    $ if [ -t 1 ]; then echo "from STDOUT"; fi
    from STDOUT
    

    Returns "from STDOUT" since the output is coming through while:

    $ (if [ -t 1 ]; then echo "from STDOUT"; fi) | cat
    

    Returns nothing, since the output is being directed to cat.

  • merging the streams did it. I thought it was something like that but I couldnt quite gte the syntax right. – Michael A Dec 6 '13 at 2:57

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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