Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I want to create a shell script that echos something if 3 directories don't exist.

Here is the code I wrote: test.sh:

if [ ! -d "/home/unix/POSTagger2" ] || [! -d "/home/unix/POSTagger2/stanford-parser-full-2015-12-09"] || [! -d "/home/unix/POSTagger2/stanford-corenlp-full-2015-12-09"]; then
echo "Nope"
fi

When I run it, I get this error:

./test.sh: line 1: [!: command not found

What's wrong with my syntax?

share|improve this question
    
In the first condition, you had it right. Doing the same in the second condition would be the first thing which I would have done… – glglgl 13 hours ago
    
[ is not a token, it is a command (another name for the command test) as such it must be separated by space(s). Similar case is ] which is a command parameter so it must be separated by a space too. – pabouk 7 hours ago
up vote 12 down vote accepted

You are missing some spaces, for example [! must be [ ! and "] must be " ] look to the corrected code:

#!/bin/bash
if 
[ ! -d "/home/unix/POSTagger2" ] || 
[ ! -d "/home/unix/POSTagger2/stanford-parser-full-2015-12-09" ] || 
[ ! -d "/home/unix/POSTagger2/stanford-corenlp-full-2015-12-09" ] 
then
      echo "Nope"
fi

Another way for your code:

#!/bin/bash
for dir in "/home/unix/POSTagger2" "/home/unix/POSTagger2/stanford-parser-full-2015-12-09" "/home/unix/POSTagger2/stanford-corenlp-full-2015-12-09"; do
     if [ ! -d "$dir" ]; then echo nope ; break; fi 
done  
share|improve this answer

You need a space between the [ and the ! for things to work correctly. This is because [ is implemented as shell-builtin command (it even used to be a separate exectuable /usr/bin/[).

You can also use:

if [ ! -d "/home/unix/POSTagger2" -o ! -d "/home/unix/POSTagger2/stanford-parser-full-2015-12-09" -o ! -d "/home/unix/POSTagger2/stanford-corenlp-full-2015-12-09") ] ; then
    echo "Nope"
fi

Bash offers an alternative [[ that is implemented as en expression. [[ uses &&, ||, etc. instead of -a, -o as operators.

if [[ ! (-d "/home/unix/POSTagger2" && -d "/home/unix/POSTagger2/stanford-parser-full-2015-12-09" && -d "/home/unix/POSTagger2/stanford-corenlp-full-2015-12-09") ]] ; then
    echo yes
fi

Edit: Thanks to comments from @LucianoAndressMartini and @pabouk for important corrections to my understanding.

share|improve this answer
1  
No! You're wrong. Try moving out the /usr/bin/[ to other folder, and you see that the conditional statement still works fine because its a bash built-in, this executable you see is not being used by bash, it is offered as a compatibility option for some ancient shell, so they can run some bash code without errors. – Luciano Andress Martini yesterday
2  
It's a builtin command in bash, but the fact that it acts like any command and needs a space still applies. – ilkkachu yesterday
1  
Yes this part of the answer still applies. It is a great answer, the only wrong thing is about thinking that "[" is not a shell built-in. – Luciano Andress Martini yesterday
1  
Well I learned something new! I never revised my view of [ since 1999, apparently. – Satya Mishra yesterday
1  
[[ is not a command. It is a token and some special characters have a different meaning between [[ and ]]. Also it is not POSIX-compliant and works only in some shells like bash or korn. See for example mywiki.wooledge.org/BashFAQ/031 – pabouk 7 hours ago

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.