简体   繁体   中英

zsh run command if process is running

I want to get some info from cmus-remote if cmus is running

#!/bin/zsh

pgrep cmus>& /dev/null
if [ $? -eq 0 ]; then
  title=$(cmus-remote -Q | grep tag | grep title | sed 's/tag title //')
  artist=$(cmus-remote -Q | grep tag | grep " artist " | sed 's/tag artist //')
  album=$(cmus-remote -Q | grep tag | grep " album " | sed 's/tag album //')
  track=$(cmus-remote -Q | grep tag | grep tracknumber | sed 's/tag tracknumber //')
  echo $track $title - $artist - $album
else
  echo ""
fi

the output for a running cmus is correct, when cmus isn't running I get

cmus-remote: cmus is not running
cmus-remote: cmus is not running
cmus-remote: cmus is not running
cmus-remote: cmus is not running
-

I have a workaround by appending >& /dev/null on each corresponding line but that's not what I want, I would like the code not to be executed at all. And I don't the output from the else case.

pgrep cmus>& /dev/null
if [ $? -eq 0 ]; then
  title=$(cmus-remote -Q | grep tag | grep title | sed 's/tag title //') > /dev/null 2>&1
  artist=$(cmus-remote -Q | grep tag | grep " artist " | sed 's/tag artist //') > /dev/null 2>&1
  album=$(cmus-remote -Q | grep tag | grep " album " | sed 's/tag album //') > /dev/null 2>&1
  track=$(cmus-remote -Q | grep tag | grep tracknumber | sed 's/tag tracknumber //') >/ dev/null 2>&1
  echo $track $title - $artist - $album
else
  echo ""
fi

Adding > /dev/null 2>&1

2 refers to the second file descriptor of the process, ie stderr .

> means redirection.

&1 means the target of the redirection should be the same location as the first file descriptor, ie stdout .

So this command first redirects stdout to /dev/null and then redirects stderr there as well. This effectively silences all output (regular or error).

In your case cmus-remote: cmus is not running is an stderr so the redirection that you should use should be able to redirect both STDOUT and STDERR

The actual problem that you seem to be having is that your pgrep is returning a hit while you're not expecting it to.

pgrep cmus>& /dev/null
if [ $? -eq 0 ]; then
  //statements here are not evaluated if pgrep\'s exit status is not equal to 0

Your pgrep exit code = zero. but it is probably not an exact match (cmus) that was found. Try narrowing your search with pgrep (ie by the usage of the u or x flag)

tip: run your bash script with -X to see what the exit code actually was and compare them to the documented exit codes on https://linux.die.net/man/1/pgrep

The best authority on whether cmus is running and whether cmus-remote can retrieve any information is cmus-remote . As such you could just replace pgrep cmus with cmus-remote as this will exit with return code 1, if cmus :

cmus-remote >& /dev/null
if [ $? -eq 0 ]; then
   # stuff
fi

Alternatively you could forego checking beforehand and reduce the amount of external commands called. Just try to parse the output cmus-remote -Q and ignore output on stderr :

#!/bin/zsh

cmus-remote -Q 2> /dev/null | awk '
BEGIN {
  tags["album"] = "";
  tags["artist"] = "";
  tags["title"] = "";
  tags["tracknumber"] = ""
}

$1 == "tag" && $2 in tags { 
  tag=$2;
  $1=$2="";
  sub(/  /,"");
  tags[tag] = $0
}

END {
  if (tag)
    printf "%s %s - %s - %s\n", tags["tracknumber"], tags["title"], tags["artist"], tags["album"];
  else
    print ""
}'

This calls cmus-remote just once and pipes stdout to awk (also called just once). If cmus is not running the error message will be passed to /dev/null . awk then parses the output of cmus-remote -Q and creates the desired output. If cmus is not running or if there were no tags, it will print an empty string.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM