7

I can grep the output of jobs, and I can grep the output of a function. But why can't I grep the output of jobs when it's in a function?

$ # yes, i can grep jobs
$ jobs
[1]+  Running          vim
[2]+  Stopped          matlab

$ jobs | grep vim
[1]+  Running          vim

$ # yes, of course i can grep a function
$ type mockjobs
mockjobs is a function
mockjobs ()
{
    echo '[1]+ Running         vim banjo'
}
$ mockjobs | grep vim
[1]+ Running         vim banjo

$ # now put those two together and surely I can grep???
$ type realjobs
realjobs is a function
realjobs ()
{
    jobs
}
$ realjobs | grep vim
$ # Nope, WTF?

$ bash --version
GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)

$ # funny though, redirection works just fine:
$ tmpfile=$(mktemp); realjobs > $tmpfile; grep vim $tmpfile; rm $tmpfile
[1]+  Running          vim

I'm not seeing a bug in the bash list, but maybe I missed it? There's reference to an issue in Bash 2.02 when jobs is part of a pipeline, but nothing recent and in a function that I can find.

What am I missing here?

4
  • 1
    +1; the source seems to indicate that jobs would print to stdout
    – Jeff Schaller
    Commented Apr 27, 2016 at 20:33
  • Uh... I'd open a bug against bash, as this is wacky.
    – thrig
    Commented Apr 27, 2016 at 21:16
  • 1
    echo "$(realjobs)" | grep vi works too.
    – cas
    Commented Apr 28, 2016 at 7:18
  • It don't work in function too.function testjobs(){jobs | grep vi}andfunction testrealjobsgrep(){realjobs | grep vi}.The testjobs can work,but the testrealjobsgrep can't work.
    – user164825
    Commented Apr 28, 2016 at 8:21

1 Answer 1

9

Eric Blake answered on the bash-bugs mailing list:

jobs is an interesting builtin - the set of jobs in a parent shell is DIFFERENT than the set of jobs in a subshell. Bash normally creates a subshell in order to do a pipeline, and since there are no jobs in that subshell, the hidden execution of jobs has nothing to report.

Bash has code to special-case jobs | when it can obviously tell that you are running the jobs builtin as the sole command of the left side of a pipe, to instead report about the jobs of the parent shell, but that special-case code cannot kick in if you hide the execution of jobs, whether by hiding it inside a function as you did, or by other means such as: eval jobs | grep vim

1
  • 1
    Looks like zsh doesn't have the special-case jobs | :|
    – Jose V
    Commented Mar 13, 2021 at 19:52

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .