How to check if $PWD is a subdirectory of a given path
To test if a string is a prefix of another, in any Bourne-style shell:
case $PWD/ in
/home/*) echo "home sweet home";;
*) echo "away from home";;
esac
The same principle works for a suffix or substring test. Note that in case
constructs, unlike in file names, *
matches any character, including a /
or an initial .
.
In shells that implement the [[ … ]]
syntax (i.e. bash, ksh and zsh), it can be used to match a string against a pattern. (Note that the [
command can only test strings for equality.)
if [[ $PWD/ = /home/* ]]; then …
If you're specifically testing whether the current directory is underneath /home
, a simple substring test is not enough, because of symbolic links.
If /home
is a filesystem of its own, test whether the current directory (.
) is on that filesystem.
if [ "$(df -P . | awk 'NR==2 {print $6}')" = "/home" ]; then
echo 'The current directory is on the /home filesystem'
fi
If you have the NetBSD, OpenBSD or GNU (i.e. Linux) readlink
, you can use readlink -f
to strip symbolic links from a path.
case $(readlink -f .)/ in $(readlink -f /home)/*) …
Otherwise, you can use pwd
to show the current directory. But you must take care not to use a shell built-in if your shell tracks cd
commands and keeps the name you used to reach the directory rather than its “actual” location.
case $(pwd -P 2>/dev/null || env PWD= pwd)/ in
"$(cd /home && { pwd -P 2>/dev/null || env PWD= pwd; })"/*) …
If you want to reliably test whether a directory is a subdirectory of another, you'll need more than just a string prefix check. Gilles' answer describes in detail how to do this test properly.
But if you do want a simple string prefix check (maybe you've already normalized your paths?), this is a good one:
test "${PWD##/home/}" != "${PWD}"
If $PWD
starts with "/home/", it gets stripped off in the left side, which means it won't match the right side, so "!=" returns true.
Crude version:
[ ${PWD:0:6} = "/home/" ]
Has the disadvantage that one has to count characters first and one can't replace /home/
by something general like $1
.
edit (thanks @Michael) for the generalization to compare with $VAR
one can use
[ "${PWD:0:${#VAR}}" = $VAR ]