So I have the following little script and keep wondering..
#!/bin/bash
if [ -d $1 ]; then
echo \'foo\'
else
echo \'bar\'
fi
.. why doe
From: info coreutils 'test invocation' (reference found through man test
):
If EXPRESSION is omitted,
test' returns false. **If EXPRESSION is a single argument,
test' returns false if the argument is null and true otherwise**. The argument can be any string, including strings like-d',
-1',--',
--help', and--version' that most other programs would treat as options. To get help and version information, invoke the commands
[ --help' and `[ --version', without the usual closing brackets.
Highlighting properly:
If EXPRESSION is a single argument, `test' returns false if the argument is null and true otherwise
So whenever we do [ something ]
it will return true
if that something
is not null:
$ [ -d ] && echo "yes"
yes
$ [ -d "" ] && echo "yes"
$
$ [ -f ] && echo "yes"
yes
$ [ t ] && echo "yes"
yes
Seeing the second one [ -d "" ] && echo "yes"
returning false, you get the way to solve this issue: quote $1
so that -d
always gets a parameter:
if [ -d "$1" ]; then
echo 'foo'
else
echo 'bar'
fi
The reason is plain and simple: The syntax does not match the case in which the -d
is recognized as an operator working on a file name. It is just taken as a string, and each non-empty string is true. Only if a second parameter to -d
is given, it is recognized as the operator to find out whether a given FILE is a directory.
The same applies to all the other operators like -e
, -r
, etc.
In your case, use double quotes to avoid running into that "problem":
[ -d "$1" ]
The reason that
[ -d ] && echo y
produces y
is that the shell interprets it as a string in the test
command and evaluates it to true. Even saying:
[ a ] && echo y
would produce y
. Quoting from help test
:
string True if string is not the null string.
That is why quoting variables is recommended. Saying:
[ -d "$1" ] && echo y
should not produce y
when called without arguments.