# sh/tcsh and jobs output



## olivier (Jun 28, 2011)

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:


```
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:


```
[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:


```
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


----------



## SirDice (Jun 28, 2011)

```
jobs | wc -l
```


----------



## olivier (Jun 28, 2011)

You didn't fully read my message:

```
jobs | wc -l
```
 didn't work under sh or tcsh.


----------



## SirDice (Jun 28, 2011)

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.


----------



## jalla (Jun 28, 2011)

You can infact redirect STDERR to STDOUT


```
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:

```
snapper:~/bin% jobs
[1]  + Suspended                     vi netapp.pl
snapper:~/bin% jobs |& wc -l
       0
snapper:~/bin%
```


----------



## olivier (Jun 28, 2011)

But 





> ```
> jobs |& wc -l
> ```


 didn't work with jobs.

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


```
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):

```
sleep 5 & ; sleep 5 & ; sleep 5 & ; jobs > tempofile; wc -l tempofile
[1] 76860
[2] 76861
[3] 76862
       3 tempofile
```


----------



## SirDice (Jun 28, 2011)

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.


----------



## jalla (Jun 28, 2011)

olivier said:
			
		

> But  didn't work with jobs.
> 
> My example still prints the jobs output and wc still counts 0 lines:
> 
> ...


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

```
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.


----------



## jilles@ (Jun 29, 2011)

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,

```
set -- $(jobs -p)
njobs=$#
```
Note that this snippet overwrites the positional parameters.


----------

