RobbG RobbG - 3 months ago 11
Bash Question

What's wrong with this shell command

I'm trying to get a shell script written for busybox on one of our embedded devices to work. The line that's causing problems is below and I've included the output of running it in a shell with the -x flag.

if [ cut -d : -f 1-3 /sys/class/net/eth0/address | grep -q -i 01:02:03 ]; then
# Do stuff

The output that is given when attempting to run it:

# sh -x ./script
+ [ cut -d : -f 1-3 /sys/class/net/eth0/address
sh: missing ]
+ grep -q -i 01:02:03 ]
grep: ]: No such file or directory
+ sync

I didn't originally write the script so I don't know when it stopped working. It appears that the command that's being used for the comparison (should return 1 if mac address prefix matches the given sample, 0 otherwise) isn't being run correctly but I don't know why it seems to be trying to seperate the commands out.


The problem is that you're using [ as if it were syntax, whereas in the shell it is a command that requires specific arguments to be passed to it.

I think that the fix should be as simple as removing the [ and corresponding ] (which is the last argument that [ expects):

if cut -d : -f 1-3 /sys/class/net/eth0/address | grep -q -i 01:02:03; then

In the shell, if works by looking at the return code of a command, whether it be [ or any other.

By the way, I don't think that the -i option to grep is doing anything useful in this case, so you can remove it.

Note that your condition can be simplified (thanks to chepner):

if grep -q '^01:02:03(:|$)' /sys/class/net/eth0/address; then

Match the start of the line, followed by the part you already had, followed by either a colon or the end of the line.


if [ "$(cut -d : -f 1-3 /sys/class/net/eth0/address)" = 01:02:03 ]; then

Do a direct string comparison on the output of the cut command, rather than piping to grep.