Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

bash: test: -v: binary operator expected

175 views
Skip to first unread message

hongy...@gmail.com

unread,
Jan 23, 2022, 8:28:10 PM1/23/22
to
See the following error:

$ test ! command -v git
bash: test: -v: binary operator expected

But both the following two methods work:

$ test ! 'command -v git'; echo $?
1
$ test ! "command -v git"; echo $?
1

Any hints for this behavior?

Regards,
HZ

hongy...@gmail.com

unread,
Jan 23, 2022, 8:35:36 PM1/23/22
to
On Monday, January 24, 2022 at 9:28:10 AM UTC+8, hongy...@gmail.com wrote:
> See the following error:
>
> $ test ! command -v git
> bash: test: -v: binary operator expected
>
> But both the following two methods work:
>
> $ test ! 'command -v git'; echo $?
> 1
> $ test ! "command -v git"; echo $?
> 1

And another working form:

$ ! (command -v git >/dev/null 2>&1); echo $?
1

So, which one should I use?

HZ

Keith Thompson

unread,
Jan 23, 2022, 8:48:24 PM1/23/22
to
"hongy...@gmail.com" <hongy...@gmail.com> writes:
> See the following error:
>
> $ test ! command -v git
> bash: test: -v: binary operator expected

As expected, since `test` has no `-v` operator.

> But both the following two methods work:
>
> $ test ! 'command -v git'; echo $?
> 1
> $ test ! "command -v git"; echo $?
> 1

As expected. Both could be simplified to `echo 1`.

They "work" in the sense that they do not print an error message. Both
test whether the specified quoted string is empty. You could replace
"command" and "git" by "foo" and "bar" respectively, with the same
results.

> Any hints for this behavior?

Yes. State what you're trying to do, then figure out what command you
need to use to do that. Also study the documentation for the `test`
command. And next time, please do all this before posting.

--
Keith Thompson (The_Other_Keith) Keith.S.T...@gmail.com
Working, but not speaking, for Philips
void Void(void) { Void(); } /* The recursive call of the void */

hongy...@gmail.com

unread,
Jan 23, 2022, 9:15:15 PM1/23/22
to
On Monday, January 24, 2022 at 9:48:24 AM UTC+8, Keith Thompson wrote:
> "hongy...@gmail.com" <hongy...@gmail.com> writes:
> > See the following error:
> >
> > $ test ! command -v git
> > bash: test: -v: binary operator expected
> As expected, since `test` has no `-v` operator.
> > But both the following two methods work:
> >
> > $ test ! 'command -v git'; echo $?
> > 1
> > $ test ! "command -v git"; echo $?
> > 1
> As expected. Both could be simplified to `echo 1`.
>
> They "work" in the sense that they do not print an error message. Both
> test whether the specified quoted string is empty. You could replace
> "command" and "git" by "foo" and "bar" respectively, with the same
> results.

Thank you for pointing this out:

$ test ! "foo -v bar"; echo $?
1
$ test ! 'foo -v bar'; echo $?
1


> > Any hints for this behavior?
> Yes. State what you're trying to do, then figure out what command you
> need to use to do that.

I want to check if the `git` command exists on the system. And also noticed the following usage here [1]:

$ if test ! `command -v git` ; then echo "git not found. Please make sure git is installed."; fi

But it seems that the command substitution, i.e., "``" or "$()" shell structure is not designed to just only obtain the exit code. So, I think the above usage is at least not idiomatic and would like to improve it.

[1] https://gitlab.com/QEF/q-e/-/merge_requests/1725#note_818943793

hongy...@gmail.com

unread,
Jan 23, 2022, 9:35:10 PM1/23/22
to
To summarize, which of the following method is preferred?

$ test ! `command -v git` ; echo $?
1

$ ! (command -v git >/dev/null 2>&1); echo $?
1

HZ

Janis Papanagnou

unread,
Jan 24, 2022, 1:59:49 AM1/24/22
to
None.

If I want to simply check for existence of a command I'd use
'whence', or 'type', or if you want 'command' then I'd write

command -v git ; echo $?

or in contexts of tests either of

command -v git || echo git non-existing

if command -v git 2>/dev/null
then echo git existing
else echo git non-existing
fi

if ! command -v git
then echo git non-existing
fi

Redirect errors as desired (one sample provided above).

>
> $ test ! `command -v git` ; echo $?
> 1
>
> $ ! (command -v git >/dev/null 2>&1); echo $?
> 1

I would avoid unnecessary stuff like subshell-expansion, and
subshells, and old `...` syntax, and test. Why do you use that
in the first place? (Just a rhetorical question. See Keith's
suggestion for a procedure to develop appropriate shell code;
the core is: "figure out what command you _need_ to use".)

Janis

>
> HZ
>

hongy...@gmail.com

unread,
Jan 24, 2022, 9:55:32 AM1/24/22
to
On Monday, January 24, 2022 at 2:59:49 PM UTC+8, Janis Papanagnou wrote:
> If I want to simply check for existence of a command I'd use
> 'whence',

$ whence
whence: command not found

> or 'type', or if you want 'command' then I'd write
> command -v git ; echo $?
> or in contexts of tests either of
>
> command -v git || echo git non-existing
>
> if command -v git 2>/dev/null
> then echo git existing
> else echo git non-existing
> fi
>
> if ! command -v git
> then echo git non-existing
> fi

Yep. This one is what I want.

> Redirect errors as desired (one sample provided above).
> >
> > $ test ! `command -v git` ; echo $?
> > 1
> >
> > $ ! (command -v git >/dev/null 2>&1); echo $?
> > 1
> I would avoid unnecessary stuff like subshell-expansion, and
> subshells, and old `...` syntax, and test.

Thank you again for your good advice.

> Why do you use that in the first place? (Just a rhetorical question. See Keith's
> suggestion for a procedure to develop appropriate shell code;
> the core is: "figure out what command you _need_ to use".)

HZ

John-Paul Stewart

unread,
Jan 24, 2022, 11:04:43 AM1/24/22
to
On 2022-01-23 20:48, Keith Thompson wrote:
> "hongy...@gmail.com" <hongy...@gmail.com> writes:
>> See the following error:
>>
>> $ test ! command -v git
>> bash: test: -v: binary operator expected
>
> As expected, since `test` has no `-v` operator.

That depends on which 'test' you're using. The bash built-in 'test'
(which the OP appears to be using) does have a (unary) -v operator.
From 'help test' in bash:

-v VAR True if the shell variable VAR is set.

For which the OP's syntax is (also) obviously wrong.

Keith Thompson

unread,
Jan 24, 2022, 4:21:02 PM1/24/22
to
"hongy...@gmail.com" <hongy...@gmail.com> writes:
> On Monday, January 24, 2022 at 2:59:49 PM UTC+8, Janis Papanagnou wrote:
>> If I want to simply check for existence of a command I'd use
>> 'whence',
>
> $ whence
> whence: command not found

"whence" is a builtin command in zsh.

[...]

Kenny McCormack

unread,
Jan 24, 2022, 8:07:43 PM1/24/22
to
In article <87zgnkn...@nosuchdomain.example.com>,
Keith Thompson <Keith.S.T...@gmail.com> wrote:
>"hongy...@gmail.com" <hongy...@gmail.com> writes:
>> On Monday, January 24, 2022 at 2:59:49 PM UTC+8, Janis Papanagnou wrote:
>>> If I want to simply check for existence of a command I'd use
>>> 'whence',
>>
>> $ whence
>> whence: command not found
>
>"whence" is a builtin command in zsh.

It is also ksh, which is, I think, where Janis is coming from.

--
"I think I understand delicate, but why do I have to wash my hands, and
be standing in cold water when doing it?"

Kaz Kylheku <k...@kylheku.com> in comp.lang.c

hongy...@gmail.com

unread,
Jan 24, 2022, 8:26:39 PM1/24/22
to
I'm not using the -v operator 'test' command, instead, here is the -v parameter of 'command':

$ help command
-v print a description of COMMAND similar to the `type' builtin

So, I really don't understand why you give the comments above.

HZ

David W. Hodgins

unread,
Jan 24, 2022, 9:22:43 PM1/24/22
to
In order to avoid having the -v option be interpreted as an option passed to the
test command, the "command -v git" must be passed as a single string to the test
command. That's done by enclosing command -v git in quotes.
test ! "command -v git"

Regards, Dave Hodgins

hongy...@gmail.com

unread,
Jan 24, 2022, 10:05:29 PM1/24/22
to
I've already posted both of the following forms:

$ test ! "command -v git"
$ test ! 'command -v git'

But when I posted the above usage, I thought it was a little strange.

HZ

Keith Thompson

unread,
Jan 25, 2022, 12:19:55 AM1/25/22
to
"hongy...@gmail.com" <hongy...@gmail.com> writes:
> On Tuesday, January 25, 2022 at 12:04:43 AM UTC+8, John-Paul Stewart wrote:
>> On 2022-01-23 20:48, Keith Thompson wrote:
>> > "hongy...@gmail.com" <hongy...@gmail.com> writes:
>> >> See the following error:
>> >>
>> >> $ test ! command -v git
>> >> bash: test: -v: binary operator expected
>> >
>> > As expected, since `test` has no `-v` operator.
>> That depends on which 'test' you're using. The bash built-in 'test'
>> (which the OP appears to be using) does have a (unary) -v operator.
>> From 'help test' in bash:
>>
>> -v VAR True if the shell variable VAR is set.
>>
>> For which the OP's syntax is (also) obviously wrong.
>
> I'm not using the -v operator 'test' command, instead, here is the -v parameter of 'command':

I know you're not *deliberately* using the -v operator of the test
command, but when you wrote:

$ test ! command -v git

you showed us an invocation of "test" that (a) would not invoke the
"command" builtin and (b) could have been a valid invocation of "test"
*if* "test" had "-v" as a binary operator. I know you intended the "-v"
to be an argument to "command", but I initially ignored that.

At that time, you had not yet told us what you were trying to do. You
had only showed us several incorrect commands, some of which you wrongly
thought were correct. I had a pretty good idea what you intended, but I
chose to (a) explain what the incorrect commands you showed us actually
do and (b) prompt you to step back and tell us what you were trying to do.

Keith Thompson

unread,
Jan 25, 2022, 12:22:06 AM1/25/22
to
That would be valid but useless. It checks whether the string
"command -v git" is empty.

hongy...@gmail.com

unread,
Jan 25, 2022, 2:31:01 AM1/25/22
to
From where can I find the specification that running test on an empty string will return 1, as denoted by the following:

$ test ''; echo $?
1

Janis Papanagnou

unread,
Jan 25, 2022, 2:46:28 AM1/25/22
to
On 25.01.2022 08:30, hongy...@gmail.com wrote:
>
> From where can I find the specification that running test on an empty

Have you tried the man pages, have you tried the POSIX specification?
You may recall that I provided easy to use links some time ago - but
wait, it was already three(!) days ago, certainly too long to recall.

Tony Oliver

unread,
Jan 25, 2022, 7:26:06 AM1/25/22
to
On Tuesday, 25 January 2022 at 07:31:01 UTC, hongy...@gmail.com wrote:
<snip>
> From where can I find the specification that running test on
> an empty string will return 1, as denoted by the following:
>
> $ test ''; echo $?
> 1

RTFM...

If you're using bash, enter the command
man bash

Search for CONDITIONAL EXPRESSIONS

Read the opening paragraphs (*PLEASE*) and then scroll down
through all the test / [ / [[ options until you get to this:

string
-n string
True if the length of string is non-zero.

And there you have it.

For the non-builtin 'test' executable, enter
man test
or
man [

Here, you will find

-n STRING
the length of STRING is nonzero

STRING equivalent to -n STRING

hongy...@gmail.com

unread,
Jan 25, 2022, 8:32:59 AM1/25/22
to
Thank you, and some more to add:

$ help test | grep -A1 -- '-n STRING'
-n STRING
STRING True if string is not empty.

Lew Pitcher

unread,
Jan 25, 2022, 10:39:33 AM1/25/22
to
On Mon, 24 Jan 2022 17:26:36 -0800, hongy...@gmail.com wrote:

> On Tuesday, January 25, 2022 at 12:04:43 AM UTC+8, John-Paul Stewart wrote:
>> On 2022-01-23 20:48, Keith Thompson wrote:
>> > "hongy...@gmail.com" <hongy...@gmail.com> writes:
>> >> See the following error:
>> >>
>> >> $ test ! command -v git
>> >> bash: test: -v: binary operator expected
>> >
>> > As expected, since `test` has no `-v` operator.
>> That depends on which 'test' you're using. The bash built-in 'test'
>> (which the OP appears to be using) does have a (unary) -v operator.
>> From 'help test' in bash:
>>
>> -v VAR True if the shell variable VAR is set.
>>
>> For which the OP's syntax is (also) obviously wrong.
>
> I'm not using the -v operator 'test' command, instead, here is the -v parameter of 'command':

No, you are NOT using the -v parameter of 'command'. That may have been
your intention, but that's NOT what you did.

The builtin test command treats it's parameters as an expression.
In your case
test ! command -v git
you gave test four parameters:
a '!', instructing test to /complement/ the results of the
following expression

a string 'command', which would be the left hand side of
a "binary" expression

a string '-v', which would be the "operator" of a "binary"
expression, and

a string 'git', which would be the right hand side of a
"binary" expression

By issuing the error message
bash: test: -v: binary operator expected
bash tells you that the builtin[1] test encountered an unexpected
and invalid '-v' operator (instead of one of the "known" binary
operators) between the 'command' string and the 'git' string.


[1] by issuing the error as "bash: test:", bash has confirmed
that you invoked the bash builtin test. Had you used the test(1)
binary, bash would not have inserted the "bash: " into the error
message, and instead issued
test: '-v': binary operator expected


HTH
--
Lew Pitcher
"In Skills, We Trust"

John-Paul Stewart

unread,
Jan 25, 2022, 2:55:08 PM1/25/22
to

On 2022-01-25 10:39, Lew Pitcher wrote:
> On Mon, 24 Jan 2022 17:26:36 -0800, hongy...@gmail.com wrote:
>> On Tuesday, January 25, 2022 at 12:04:43 AM UTC+8, John-Paul Stewart wrote:
>>> On 2022-01-23 20:48, Keith Thompson wrote:
>>>> "hongy...@gmail.com" <hongy...@gmail.com> writes:
>>>>> See the following error:
>>>>>
>>>>> $ test ! command -v git
>>>>> bash: test: -v: binary operator expected
>>>>
>>>> As expected, since `test` has no `-v` operator.
>>> That depends on which 'test' you're using. The bash built-in 'test'
>>> (which the OP appears to be using) does have a (unary) -v operator.
>>> From 'help test' in bash:
>>>
>>> -v VAR True if the shell variable VAR is set.
>>>
>>> For which the OP's syntax is (also) obviously wrong.
>>
>> I'm not using the -v operator 'test' command, instead, here is the -v
>> parameter of 'command':
>
> No, you are NOT using the -v parameter of 'command'. That may have been
> your intention, but that's NOT what you did.
[snip]
> [1] by issuing the error as "bash: test:", bash has confirmed
> that you invoked the bash builtin test. Had you used the test(1)
> binary, bash would not have inserted the "bash: " into the error
> message, and instead issued
> test: '-v': binary operator expected

In addition, the error message is explicitly saying that it was 'test'
that was (mis-)interpreting the -v operator, rather than it being parsed
as an option to 'command'.

The mention of 'test' in the error message should have been a big clue
to the OP that the line was not being interpreted the way he expected.

hongy...@gmail.com

unread,
Jan 25, 2022, 7:29:18 PM1/25/22
to
Thank you for your in-depth analysis. I checked and confirmed with the following tests:

$ ( set -x ; test ! command -v git )
+ test '!' command -v git
bash: test: -v: binary operator expected
$ ( set -x ; test ! 'command -v git' )
+ test '!' 'command -v git'
$ ( set -x ; test ! "command -v git" )
+ test '!' 'command -v git'


> [1] by issuing the error as "bash: test:", bash has confirmed
> that you invoked the bash builtin test. Had you used the test(1)
> binary, bash would not have inserted the "bash: " into the error
> message, and instead issued
> test: '-v': binary operator expected

I confirmed your above conclusion:

$ /bin/test command -v git
/bin/test: ā€˜-v’: binary operator expected

HZ

hongy...@gmail.com

unread,
Jan 25, 2022, 7:32:33 PM1/25/22
to
On Wednesday, January 26, 2022 at 3:55:08 AM UTC+8, John-Paul Stewart wrote:
> In addition, the error message is explicitly saying that it was 'test'
> that was (mis-)interpreting the -v operator, rather than it being parsed
> as an option to 'command'.
>
> The mention of 'test' in the error message should have been a big clue
> to the OP that the line was not being interpreted the way he expected.

Thank you for pointing out and emphasizing this.

HZ

Chris Elvidge

unread,
Jan 26, 2022, 6:56:30 AM1/26/22
to
I know I'm stupid to ask this, but why do you insist on 'test'ing a
linux/unix command?
Surely:
command -v git && echo "git installed" || echo "git not installed"
would suffice.


--
Chris Elvidge
England

hongy...@gmail.com

unread,
Jan 26, 2022, 7:51:05 AM1/26/22
to
On Wednesday, January 26, 2022 at 7:56:30 PM UTC+8, Chris Elvidge wrote:
> I know I'm stupid to ask this,

Absolutely no. Everyone does things according to their own logic, which is not so stupid, at least from their own point of view.

> but why do you insist on 'test'ing a linux/unix command?

Just in order to verify the above-mentioned working mechanism of test.

> Surely:
> command -v git && echo "git installed" || echo "git not installed"
> would suffice.

Agreed.

Chris Elvidge

unread,
Jan 26, 2022, 8:33:07 AM1/26/22
to
On 26/01/2022 12:51, hongy...@gmail.com wrote:
> On Wednesday, January 26, 2022 at 7:56:30 PM UTC+8, Chris Elvidge wrote:
>> I know I'm stupid to ask this,
>
> Absolutely no. Everyone does things according to their own logic, which is not so stupid, at least from their own point of view.
>
>> but why do you insist on 'test'ing a linux/unix command?
>
> Just in order to verify the above-mentioned working mechanism of test.

But you didn't. You verified that you had the command structure wrong.
Try: test $(command -v git)
Or: C=$(command -v git); test -v C
At least then you know which -v is implemented when.

>
>> Surely:
>> command -v git && echo "git installed" || echo "git not installed"
>> would suffice.
>
> Agreed.
>


--
Chris Elvidge
England

hongy...@gmail.com

unread,
Jan 26, 2022, 11:45:37 PM1/26/22
to
On Wednesday, January 26, 2022 at 9:33:07 PM UTC+8, Chris Elvidge wrote:
> On 26/01/2022 12:51, hongy...@gmail.com wrote:
> > Just in order to verify the above-mentioned working mechanism of test.
> But you didn't. You verified that you had the command structure wrong.
> Try: test $(command -v git)
> Or: C=$(command -v git); test -v C
> At least then you know which -v is implemented when.

Thank you for providing me with clearer verification examples.

Lew Pitcher

unread,
Jan 27, 2022, 9:33:28 AM1/27/22
to
No, you are just using the wrong tools.

Try

if ! command -v git >/dev/null
then
echo git not found
fi

or
! command -v git >/dev/null && echo git not found

or, better yet,
command -v git >/dev/null || echo git not found


You see, the bash <<if>> construct evaluates exit codes, as do
both the bash <<&&>> and <<||>> constructs. But, neither the
bash <<test>> construct nor test(1) evaluate exit codes as part
of their expression, and to get them to evaluate exit codes, you
have to go through the contortions of first capturing the exit
code as a string, and then having <<test>> or test(1) check the
contents of that string.

If you insist on using the bash <<test>> builtin or test(1), then
you /don't/ need to check the exit code from <<command>>. As
<<command>> (with the -v option) will output the path to the command
(on success) or nothing (on failure), both of which the shell handles
as strings, <<test>> or test(1) can check the results from <<command>>
without resorting to checking it's exit code.

And, that's where
if test ! `command -v git`
then
echo "git not found. Please make sure git is installed."
fi
comes from.


> [1] https://gitlab.com/QEF/q-e/-/merge_requests/1725#note_818943793
>
>> Also study the documentation for the `test`
>> command. And next time, please do all this before posting.




0 new messages