Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I have a jobscount() function:

jobscount() {
   local stopped='$(jobs -s | wc -l | tr -d " ")'
   local running='$(jobs -r | wc -l | tr -d " ")'
   echo -n "${running}r/${stopped}s"
}

I use this function in my $PS1:

PS1=" \w $(jobscount) \$ "

The only problem is if there is no background process running or there is no stopped jobs, this function uselessly occupies $PS1 space. What I want is if either of the stopped or running value is more than 0, only then it shows up.

share|improve this question
1  
Related question. –  jw013 Mar 20 '13 at 15:40
2  
Is the tr -d ' ' necessary? –  jw013 Mar 20 '13 at 15:44

3 Answers 3

First of all, I suggest to fix your quoting. You current function does not output useful data when run stand-alone from the command prompt.

Then add a condition, using the OR list separator, before the echo:

jobscount() {
  local stopped=$(jobs -sp | wc -l)
  local running=$(jobs -rp | wc -l)
  ((running+stopped)) && echo -n "${running}r/${stopped}s "
}

PS1=' \w $(jobscount)\$ '

I also suggest to add -p to the jobs calls so they output only process PIDs. Otherwise a yes $'foo\nbar' & command, listed on 2 lines, would be counted twice.

share|improve this answer
    
Here is what happens. 1. When I remove the quotes around them, the function don't work (there is always 0r/0s). 2. After adding ((running+stopped)) &&, I get bash: ((: $(jobs -rp | wc -l): syntax error: operand expected (error token is "$(jobs -rp | wc -l)") as error when opening a new terminal. –  Santosh Kumar Mar 20 '13 at 15:58
    
Works for me: pastebin.com/vQtW9qJC . Have you noticed that I changed both the function (removed single quotes) and the PS1 (changed double quotes to single ones)? –  manatwork Mar 20 '13 at 16:09
    
Your solution works correct if I start bash with --norc and paste the function online. The result is total different if I put that in my .bashrc file. –  Santosh Kumar Mar 20 '13 at 16:39
    
I tried it both directly from the command line and from my .bashrc. I had no issues. By the way, I put it at the very end of my .bashrc to make sure nothing alters the prompt after it. Do you have other PS1 assignments there? If yes, post them so we can suggest a way to make all your prompt features compatible. –  manatwork Mar 20 '13 at 16:46

I'm using a variant of this to show the exit code only if it's non-zero:

PS1=' \w $(running=$(jobscount); [ "${running:-0}" -eq 0 ] || printf %s "$running") \$ '

The code inside will run every time the prompt is displayed.

share|improve this answer

Since you're running this at every prompt, it's worth saving a few external calls.

To show the count only if there are background jobs, check the numbers and don't print anything if they're all 0.

Run jobs -p to get just the process IDs, it's easier to parse reliably.

jobscount() {
  set $(jobs -rp)
  set $# $(jobs -sp)
  set $1 $(($#-1))
  if [ $1 -ne 0 ] || [ $2 -ne 0 ]; then echo "${1}r/${2}s"; fi
}
PS1=' \w $(jobscount) \$ '

By the way, note the quotes around the right-hand side when assigning to PS1. With double quotes, the function is called when you set the variable. You need to use single quotes, so that the value of PS1 contains the text $(jobscount) and the function is called each time the prompt is displayed.

You can save one fork by using PROMPT_COMMAND to set a variable instead of using a function's output.

set_jobscount () {
  set $(jobs -rp)
  set $# $(jobs -sp)
  set $1 $(($#-1))
  if [ $1 -ne 0 ] || [ $2 -ne 0 ]; then
    jobscount="${1}r/${2}s"
  else
    jobscount=
  fi
}
PROMPT_COMMAND="$PROMPT_COMMAND
set_jobscount"
PS1=' \w ${jobscount} \$ '

As usual it's simpler (if cryptic-looking) in zsh.

precmd () {
  jobscount=${(M)#${jobstates%%:*}:#running}r/${(M)#${jobstates%%:*}:#suspended}s
  if [[ $jobscount == r0/s0 ]]; then jobscount=; fi
}
setopt prompt_subst
PS1='… ${jobscount} …'
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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