sh/tcsh and jobs output

olivier

Developer
Hi all,

I've got a problem with sh/tcsh jobs output. My simple goal is to get the number of running jobs, like in this example:

Code:
sleep 5 & ; sleep 5 & ; sleep 5 & ; jobs | wc -l

But the output is not what I'm waiting for: Only "3" in this example, but this:

Code:
[1] 75677
[2] 75678
[3] 75679
       0
The output of jobs is not sent to wc.

I need to use a very dirty hack for my needs:

Code:
sleep 5 & ; sleep 5 & ; sleep 5 & ; jobs > tempofile
wc -l tempofile | tr -s " " | cut -f 2 -d " "

Did someone know how to avoid the use of a temporary file for counting jobs number in sh or tcsh?

Thanks
 
You didn't fully read my message:
Code:
jobs | wc -l
didn't work under sh or tcsh.
 
Yeah, noticed that. It seems it's because jobs writes to STDERR. Unfortunately you cannot redirect STDERR to STDOUT with tcsh. Which is one of the reasons why it's crap for scripting.
 
You can infact redirect STDERR to STDOUT

Code:
snapper:~/bin% blah 
blah: Command not found.
snapper:~/bin% blah |& wc -l
       1
snapper:~/bin%

I suppose the pipeline is executed by forking a subshell so the result of wc is correct:
Code:
snapper:~/bin% jobs
[1]  + Suspended                     vi netapp.pl
snapper:~/bin% jobs |& wc -l
       0
snapper:~/bin%
 
But
Code:
jobs |& wc -l
didn't work with jobs.

My example still print the jobs output and wc still counts 0 lines:

Code:
sleep 5 & ; sleep 5 & ; sleep 5 & ; jobs |& wc -l
[1] 76816
[2] 76817
[3] 76818
       0

I still need to use a file redirection to permit wc to count the lines (3):
Code:
sleep 5 & ; sleep 5 & ; sleep 5 & ; jobs > tempofile; wc -l tempofile
[1] 76860
[2] 76861
[3] 76862
       3 tempofile
 
jalla said:
You can infact redirect STDERR to STDOUT
Ah, yes. You just can't redirect them seperately. I actually never use tcsh for scripting. I do love it as an interactive shell though.
 
olivier said:
But didn't work with jobs.

My example still prints the jobs output and wc still counts 0 lines:

Code:
sleep 5 & ; sleep 5 & ; sleep 5 & ; jobs |& wc -l
[1] 76816
[2] 76817
[3] 76818
       0
The output you see does not come from jobs. That comes from each invocation of sleep.
Just leave out the jobs part to convince yourself
Code:
snapper:~% sleep 1 &; sleep 1 &
[1] 13719
[2] 13720
snapper:~%

Jobs in your piece of code produces no output, and that is the correct thing.
 
You cannot pipe the output of jobs to something because sh and tcsh always run the left-hand side of a pipe in a subshell environment with its own job list that starts off empty. PR PR bin/34811 asks for this to be changed in sh but this is unlikely to be in 9.0.

In sh you can still get at the output of jobs by placing it by itself in a command substitution. This feature is properly documented in the man page in 9.0 (though not yet on man.freebsd.org) but works in older FreeBSD versions as well. In other implementations it is common but not ubiquitous. For example,
Code:
set -- $(jobs -p)
njobs=$#
Note that this snippet overwrites the positional parameters.
 
Back
Top