[ "$(pwd)" != "$PS_APP_HOME" ] -o [ "$(pwd)" != "$PS_CUST_HOME" ]
calls the [
command with the following as arguments:
- output of
pwd
¹,
!=
,
- the contents of the
PS_APP_HOME
variable,
]
,
-o
,
[
,
- the output of another invocation of
pwd
,
!=
,
- the contents of the
PS_CUST_HOME
variable, and
]
.
The ]
is meant to be the last argument, so when [
sees -o
after the first ]
, it is confused.
[
has a deprecated -o
operator for OR, but that's meant to be used as [ some-condition -o some-other-condition ]
. It should however not be used as it makes for unreliable test expressions.
Here, using OR also doesn't make sense. The current working directory cannot be at the same time something ($PS_APP_HOME
) and something else ($PS_CUSTOM_HOME
), so at least one of "$(pwd)" != "$PS_APP_HOME"
or "$(pwd)" != "$PS_CUST_HOME"
is going to be true. Presumably you meant AND instead of OR. So:
with standard syntax:
if [ "$PWD" != "$PS_APP_HOME" ] && [ "$PWD" != "$PS_CUST_HOME" ]; then
echo current directory is neither the APP nor CUST home
fi
(where we run a second [
command if the first one was successful using the &&
shell (not [
) operator).
Korn-like syntax:
if [[ $PWD != "$PS_APP_HOME" && $PWD != "$PS_CUST_HOME" ]]; then
echo current directory is neither the APP nor CUST home
fi
or
if [[ ! ($PWD = "$PS_APP_HOME" || $PWD = "$PS_CUST_HOME") ]]; then
echo current directory is neither the APP nor CUST home
fi
where [[...]]
is a special construct with its own conditional expression micro-language code inside which also has some &&
(and) / ||
(or), !
(not) boolean operators.
Though you could also use case
:
case $PWD in
("$PS_APP_HOME" | "$PS_CUST_HOME") ;;
(*) echo current directory is neither the APP nor CUST home
esac
$PWD
is like $(pwd)
except it's more efficient as it doesn't need to fork another process and get its output through a pipe and means it still works if the path of the current working directory ends in newline characters.²
Beware the double quotes above are important, I've only put them where they are strictly necessary (to prevent split+glob in the arguments of [
and to prevent variable values to be taken as a pattern in the argument the !=
/ =
operators of the [[...]]
construct or case
), though having all expansions quoted would not harm.
Instead of doing lexical comparisons, also note that ksh/bash/zsh's [[....]]
and most [
implementations including the [
builtin of bash
support a -ef
operator, to check whether two files are the same (after symlink resolution), so you could use that instead of =
:
if [[ ! (. -ef $PS_APP_HOME || . -ef $PS_CUST_HOME) ]]; then
echo current directory is neither the APP nor CUST home
fi
Or for sh
(most sh
s):
if [ ! . -ef "$PS_APP_HOME" ] && [ ! . -ef "$PS_CUST_HOME" ]; then
echo current directory is neither the APP nor CUST home
fi
Here also using .
which unlike $PWD
or $(pwd)
is guaranteed to refer to the current working directory.
That way if $PWD
is /opt/app
or /some/link/to/app
and $PS_APP_HOME
is /opt/./app
or /opt/foo/../app
or /opt//app
for instance, that will still work.
¹ stripped of all trailing newline characters, so maybe not the current working directory.
² in some shells, $PWD
might give you stale information though if the current working directory has been renamed under your feet. But then again, that's also true of pwd
in some shells which just output the value of $PWD
and only update it upon cd
/pushd
/popd
.
pwd
to get the current dir in bash. bash automatically keeps the$PWD
variable up-to-date with the current directory.[
is a command, nothing more.[
requires]
as the last argument, so it looks like some special syntax, but it's not.[
is neither a part of the syntax ofif
, nor a keyword in the shell that makes the shell parse things differently.[
usually is a builtin, but it still behaves like a command.[
can be/usr/bin/[
or so. OTOH[[
is special in Bash.AND
, notOR
. See stackoverflow.com/questions/26337003/…