Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It's 100% free, no registration required.

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

E.g. check if $PWD is a subdirectory of /home. In other words I'm searching for a bash string operation to check if one string starts with another.

share|improve this question
up vote 15 down vote accepted

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.

share|improve this answer
1  
+1 perfect, and for a more general case: [ "${PWD##$VAR}" != "$PWD" ] And if this were a [code-golf ](stackoverflow.com/questions/tagged/code-golf)question you'd have beaten me by two chars ;-) Also it looks more readable... – Tobias Kienzler Jan 26 '11 at 11:16
    
FWIW, this may be also useful: ${PWD/#$HOME/\~} – user1338062 Nov 1 '15 at 8:24
    
Alright, but how about PWD="/home/../etc/" – Alexis Peters Mar 22 at 14:21
1  
@AlexisPeters: You're right: I was focusing on the "string prefix" part of the question, and I have edited to make that more clear. Gilles has nicely covered the proper way to check for subdirectories. – Jander Mar 22 at 20:34

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 || command pwd)/ in
  $(cd /home && { pwd -P . 2>/dev/null || command pwd; })/*) …
share|improve this answer
    
+1 Thanks for this exhaustive answer. I didn't consider links and filesystem peculiarities when asking this, but it's definitely good to know – Tobias Kienzler Jan 26 '11 at 11:08
    
+1 for Bourne/POSIX compatible solution. – ayekat Dec 5 '15 at 8:43

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 ]
share|improve this answer
4  
${#var} is the length of $var, so you can generalize it as [ "${PWD:0:${#1}}" = "$1" ] – Michael Mrozek Jan 25 '11 at 15:58
    
@Michael Mrozek♦: Thanks, works perfect :) – Tobias Kienzler Jan 26 '11 at 11:03

Using awk:

echo $PWD | awk -v h="/home" '$0 ~ h {print "MATCH"}'
share|improve this answer
    
+1 for working, but a bit slower than a native bash test – Tobias Kienzler Jan 26 '11 at 11:13

I don't understand the question too well, but to find the parent of $PWD, do dirname $PWD. To find the parent of the parent, run dirname $(dirname $PWD), and so on...

share|improve this answer
    
That would only work if I knew the depth, otherwise I end up with /. Ok, I could check recursively, but isn't there something easier? – Tobias Kienzler Jan 25 '11 at 15:41
    
@tob If only I knew shell programming ;-) – Tshepang Jan 25 '11 at 16:06

Hm, it's pity that [ doesn't have an option of testing STRING1 starts with STRING2 condition.

You may try echo $PWD | grep '^$VAR', but it can fail in interesting ways when VAR contains special symbols.

awk's index function should be able to do the trick. But all this seems just too heavy for such an easy thing to test.

share|improve this answer
    
[[ does regexp so yo get startswith [[ $PWD =~ ^\/home\/ ]] – teknopaul Dec 2 '15 at 23:32

If the searched part of path is found I "empty" the variable :

[[ -z "${PWD//*\/home\/*/}" ]] && echo "toto"
share|improve this answer

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.