tags:

views:

84

answers:

5

I have code matching:

if [ $LAST_MODIFIED -lt 3600 || ! -f "$i" ]; then
    wget $WGET_OPTS $BASE$i
    LAST_MODIFIED=`echo "\`date +%s\` - \`stat -c %Y $i\`" | bc`
    if [ $LAST_MODIFIED -lt 500 ]; then
        $FILES_MODIFIED++
    fi
fi

$i is defined via

for i in `/bin/grep ".gz" index.html | awk -F\" '{print $2}'`

however, bash tells me

[: missing `]'

and

-f: command not found

Why?

+4  A: 

Should be

if [ $LAST_MODIFIED -lt 3600 ] || ! [ -f "$i" ]; then

[ (and !) are shell built-ins. They are not part of the syntax for if.

Dave Hinton
If your interested, [ is generally a symbolic link to the 'test' command. So you can do a man on test.
ssteidl
+1  A: 

Try to rewrite your if as

if [ cond a ] || [ cond b ]; then
...
fi
Rickard
`-bash: [: too many arguments`
Dennis Williamson
A: 

[ is an actual builtin command, that requires ] as it's last argument.

However your syntax makes the last argument to [ "3600", and then starts a new command..

Try making the command between the [ and ] a single command.

John Weldon
`-bash: syntax error near unexpected token '$LAST_MODIFIED'`
Dennis Williamson
sorry... powershell syntax... I'll update with bash syntax
John Weldon
really all the other answers are great, so I'll just remove the bad example.
John Weldon
+9  A: 

You should either use [[ ... ]] instead of [ ... ] or use -o instead of ||.

if [[ $LAST_MODIFIED -lt 3600 || ! -f "$i" ]]; then

or:

if [ $LAST_MODIFIED -lt 3600 -o ! -f "$i" ]; then

See here: http://www.ibm.com/developerworks/library/l-bash-test.html

Mark Byers
A: 

Keep in mind that the bash [ built-in command must honor the syntax requirements of the external /bin/[ command (usually a link to /bin/test) in order to maintain backward compatibility with the archaic versions of sh in which test ([) was NOT internal to the shell.

In order to honor that level of compatibility the parser must treat || as a separator to a new command, thus terminating the [ command. When /bin/test is called as [ (it checks its on argv[0]) then it requires the closing "]" as a parameter.

Use -o (or) in your test ([) commands.

(Personally I think it's a bad idea do use the [ form of test for exactly this reason. Novices will think of it as a syntactic feature ... a sort of conditional expression construct to the if statement, expecting semantics which are not consistent with its implementation as command. So I teach it as test even though I use it (sometimes) as [ because the practice is so widespread.

Jim Dennis