Question

Given this driver function that only produces output given certain input:

function driver -a arg
  test $arg = 1; and echo OK
  return 0
end

Things work OK when the function emits output:

$ driver 1 | od -c
0000000   O   K  \n
0000003
$ test -z (driver 1); and echo no output; or echo some output
some output
$ test -n (driver 1); and echo some output; or echo no output
some output

But in the no output case:

$ driver 0 | od -c
0000000
$ test -z (driver 0); and echo no output; or echo some output
no output
$ test -n (driver 0); and echo some output; or echo no output
some output

Is this a bug?

Was it helpful?

Solution

It's not a bug!

The command substitution (driver X) executes the driver function, and then turns each output line into an argument. In the case of (driver 0), there's no output, so you get zero arguments. So the no output case is equivalent to running test -z and test -n.

Good old IEEE 1003.1 tells us what test must do in this case:

1 argument: Exit true(0) if $1 is not null; otherwise, exit false

So when -n is the only argument, it loses its status as a flag, and you just end up testing '-n' for non-nullity (which of course it passes).

You can see the same behavior in bash:

> test -n `echo -n` ; echo $?
0

In fish, if you want to check if a string is non-empty, you can use count:

if count (driver 0) > /dev/null
    # output!
end

You can also use an intermediate variable with test:

set -l tmp (driver 0)
test -n "$tmp" ; and echo some output; or echo no output

The quotes ensures that $tmp always becomes one argument (possibly empty).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top