Tim Wilder
Tim Wilder

Reputation: 1647

[: too many arguments on Cygwin Shell script

I inherited some shell scripts written to do automated performance testing without having any shell scripting knowledge. I skimmed through a few guides and played around with the language until I could do my project. It mostly went well, but I'm stuck on something I absolutely have not been able to find an answer to anywhere else.

Part of the old code ssh's into a server used in the testing with a script as an argument. I need this script do do different things on Windows and Linux. My best solution so far is to grep for Cygwin in uname -a's output, and if found, do the Windows code.

Unfortunately the script is going belly up both when passed via ssh, and when executed through Cygwin on the Windows system.

#!/bin/bash
if [ `uname -a | grep "Cygwin"` ]; then
    echo "ARRGG WINDOWS!"
else
    echo "Some Linux command."
fi

yields:

./test.sh: line 2: [: too many arguments

and then branches to the not-windows logic. The same thing appears to run fine on any Linux distribution I've tried.

I'm left with three questions. Why am I getting this exception, what are some good ways for me to get answers to hyper-specific questions like this (intersection between shell scripting, Cygwin, ssh, and one error) besides Googling, and is there a better, more canonical way to test for platform?

Thanks for your time, and I'll be happy to provide any additional info that will help.

The troublesome clause was copied verbatim, the rest was made up for SO.

Upvotes: 1

Views: 1241

Answers (2)

Barton Chittenden
Barton Chittenden

Reputation: 4418

I tried your command, it executed without error on bash 4.2.37.

It will also work without the square brackets or back-ticks -- if tests the return code of the next command... you can use the test command, which can also be spelled [, but it will also work with the return code of grep or even : which is always true.

#!/bin/bash
if uname -a | grep Cygwin > /dev/null; then
     echo "ARRGG WINDOWS!"
else
     echo "Some Linux command."
fi

Note, there is also a bash environment variable $OSTYPE which will be linux-gnu under Linux.

There's an in-depth discussion here: Detect the OS from a Bash script

Upvotes: 2

Jonathan Leffler
Jonathan Leffler

Reputation: 754560

The output for uname -a on Cygwin will be many words including Cygwin. Each word will be an argument to test (aka [). Hence the complaint. You probably want:

case "$(uname -a)" in
(*Cygwin*) echo "Oh bother!";;
(*)        echo "Phew!";;
esac

or:

if [ -n "$(uname -a | grep Cygwin)" ]
then echo "Oh bother!"
else echo "Phew!"
fi

or:

if [ $(uname) = Cygwin ]
then echo "Oh bother!"
else echo "Phew!"
fi

This gets either Cygwin or Linux — or Darwin on Mac OS X, and equivalent names on AIX, Solaris, HP-UX — and avoids the multiple arguments issue and only runs one command instead of two.

Upvotes: 2

Related Questions