21

I'm writing a very simple shell scripts that would looked at the log of all failed tests, and print out all the name of all files in the current directory that are in the log

 1  #! /bin/sh

 2  for file in *
 3  do
 4      echo "checking: $file"
 5      if [$(grep $file failed.txt -c) -ne 0]
 6      then
 7          echo "$file FAILED"
 8      fi
 9  done

When I execute it, I get this error:

line 6: [0: command not found

Does anyone have any idea why?

Thanks!!

2
  • You want to move the -ne to the start of the if-statement Commented May 14, 2012 at 15:33
  • 5
    you're missing a space: if [ $(grep $file failed.txt -c) -ne 0 ] Commented May 14, 2012 at 15:35

3 Answers 3

27

[ is actually a command in linux (like bash or cat or grep).

$(grep $file failed.txt -c) is a command substitution which in your case evaluated to 0. Thus the line now reads [0 -ne 0], which is interpreted as run a program called [0 with arguments -ne 0].

What you should write instead is [ $(grep $file failed.txt -c) -ne 0 ]. Shell scripts require that there be spaces between the opening and closing square braces. Otherwise you change the command that is executed (the closing ] indicates that there are no more arguments to be read.

So now the command evaluates to [ 0 -ne 0 ]. You can try executing this in your shell to see what happens. [ exits with a value of 0 if the expression is true and 1 if it is false. You can see the exit value by echoing $? (the exit value of the last command to be run).

Sign up to request clarification or add additional context in comments.

5 Comments

You should still avoid the Useless Use of Backticks. partmaps.org/era/unix/award.html#backticks (check out the separate example in particular).
@tripleee Good advice, but I wouldn't say particularly relevant in this case as the output of grep in this case is likely to be tiny in comparison to ARG_LIMIT. Though as someone pointed out in another comment if grep $file failed.txt -q is the ideal solution. I'm generally not keen on using output redirects as they make scripts harder to read (more tokens for me to read and process).
Oh, absolutely; if grep -q is what I was getting at, too. (You seem to have the search pattern and the file argument reversed?)
@tripleee I thought that at first about the arguments, but the check the OP. He's searching for whether a file name exists in failed.txt.
Sorry, I was comparing to @Rony's answer, but his is the one with the wrong argument order.
7

Instead of testing the count, you can test the return code of grep:

if grep -q $file failed.txt &>/dev/null

5 Comments

Well, you could always one line the entire script as well. cat failed.txt | xargs ls -f1 2>/dev/null
You gain a bit of efficiency using grep -q -- if there's a match, grep exits immediately.
Note that the '&>' redirection is not posix. Bash will interpret it the same as '>/dev/null 2>&1', but not all shells will. ( eg, dash will invoke the grep in the background and truncate /dev/null )
@WilliamPursell: Useful for other shells, but the question is specifically about Bash.
The question is also tagged 'shell', and many people reading these questions know very little about portability issues. It is important to mention shell specific cases when they are used. There's nothing wrong with using shell specific features, but such usage should be done with awareness.
1

The script can be

#!/bin/sh

for file in *; do
    echo "checking: $file"
    grep failed.txt $file && echo "$file FAILED"
done

or, as an one-liner in user shell command history:

for file in *; do { echo "checking: $file" && grep failed.txt $file && echo "$file FAILED"; done

in man grep

EXIT STATUS
The exit status is 0 if selected lines are found, and 1 if not found. If an error occurred the exit status is 2. (Note: POSIX error handling code should check for '2' or greater.)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.