I can't make sense of these return values.

When I run jobs -s | wc -l, I get different results depending on what directory I'm in.

If I'm in the directory that I returned to after suspending the job, I get the correct answer.

If I'm in any other directory, I get the correct answer + 1.

See screenshot:

enter image description here

I also ran jobs -s | > test.txt and got a single line document, then ran wc -l < test.txt and got the right output.

Any idea what's causing this? As you can see, it's messing up my background jobs indicator in my shell prompt (right side, blue).

Any suggestions on how to fix this function would be greatly appreciated:

#tells us how many jobs are in the background  
function jobs_status() {
  count=$(jobs -s | wc -l)
  if [[ $count -ne "0" ]]; then
    echo "$bg_jobs$split$fg_text $count $fg_jobs"

Because there are two lines in later case, one being shown, one not because it is being shown in a subshell with a trailing newline that is being counted. I have checked zsh and bash, this behavior exists in zsh, bash behaves similarly with different formatting.

Take a look at the following ASCII dump from zsh:

/tmp/test% jobs
[1]  + running    tail -f /var/log/syslog

/tmp/test% jobs | wc -l

/tmp/test% jobs | od -c
0000000   [   1   ]           +       r   u   n   n   i   n   g        
0000020           t   a   i   l       -   f       /   v   a   r   /   l
0000040   o   g   /   s   y   s   l   o   g  \n

/tmp/test% cd ..

/tmp% jobs | wc -l

/tmp% jobs | od -c
0000000   [   1   ]           +       r   u   n   n   i   n   g        
0000020           t   a   i   l       -   f       /   v   a   r   /   l
0000040   o   g   /   s   y   s   l   o   g  \n   (   p   w   d       n
0000060   o   w   :       /   t   m   p   )  \n

It seems shell is keeping track of the current working directory, look at ( p w d n 0000060 o w : / t m p ), the parentheses indicate subshell.

Here is the relevant source code of zsh, jobs.c:

/* print "(pwd now: foo)" messages: with (lng & 4) we are printing
 * the directory where the job is running, otherwise the current directory

    if ((lng & 4) || (interact && job == thisjob &&
                      jn->pwd && strcmp(jn->pwd, pwd))) {
        doneprint = 1;
        fprintf(fout, "(pwd %s: ", (lng & 4) ? "" : "now");
        fprintdir(((lng & 4) && jn->pwd) ? jn->pwd : pwd, fout);
        fprintf(fout, ")\n");

While bash has:

      if (strcmp (temp, jobs[job_index]->wd) != 0)
        fprintf (stream,
          _("  (wd: %s)"), polite_directory_format (jobs[job_index]->wd));

To get what you want you can run jobs in a subshell:

( jobs ) | wc -l
  • Very interesting. Two questions: 1) Why isn't that line of text visible? 2) Any idea how I can fix the function? (edited into original post). Thanks! – JoshuaD Dec 28 '15 at 7:17
  • @JoshuaD check my edits – heemayl Dec 28 '15 at 7:29
  • Thanks. Answer accepted. Would you mind explaining why the line is invisible, and why running in a subshell fixes the problem? – JoshuaD Dec 28 '15 at 7:30

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.