3

I have some code like this in a script (bash) file:

if [ ! -d $dir ]; then
    cd $dir/..
    git clone http://...
fi

Of course as written this doesn't work since $dir does not exist. Is there a good way to strip out the top-level directory here?

2 Answers 2

4

Use parameter expansion to remove the last step in a path. Do it in a loop until you find an existing dir:

while [[ $dir && ! -d $dir ]] ; do
    dir=${dir%/*}
done
if [[ -d $dir ]] ; then
    echo $dir exists.
fi
1
  • @drewbenn: Right, just prepend [[ $dir == */* ]] || exit. Commented Sep 9, 2014 at 20:36
1
chkdir() for d do ${d:+:} continue
(   cd -- "$d" && d= ||
    while cd -- "${d%"${d#*/}"}." && ! {
    [ -n "${d##*/*}" ] && break
};  do  d=${d#*/}; d=${d#"${d%%[!/]*}"}; done
    pwd -P; printf "${d:+./%s\n}\n" "$d"
);  done 2>/dev/null

That's a little function that should handle any path you throw at it. It will try to walk the tree if it cannot simply change directly into the directory. It breaks the loop when it should. It handles multiple arguments. For each it will either print only the whole canonical path to the directory or it will print as far as it managed to get then whatever remains of its argument's path. It skips empty arguments.

Here it is in action:

$ chkdir /tmp/chrome/some/nonexistent/path .. ../test *

/tmp/chrome
./some/nonexistent/path

/home/mikeserv

/home/mikeserv/test

/home/mikeserv/test
./file1

/home/mikeserv/test
./file2

/home/mikeserv/test
./file3

If I remove the stderr redirect on the end there and enable debugging you can see how it works.

+ chkdir .. ///tmp/.//////chrome/not/
+ : continue
+ cd -- ..
+ d=
+ pwd -P
/home/mikeserv
+ printf \n

+ : continue
+ cd -- ///tmp/.//////chrome/not/
dash: 2: cd: can't cd to ///tmp/.//////chrome/not/
+ cd -- /.
+ [ -n  ]
+ d=//tmp/.//////chrome/not/
+ d=tmp/.//////chrome/not/
+ cd -- tmp/.
+ [ -n  ]
+ d=.//////chrome/not/
+ d=.//////chrome/not/
+ cd -- ./.
+ [ -n  ]
+ d=/////chrome/not/
+ d=chrome/not/
+ cd -- chrome/.
+ [ -n  ]
+ d=not/
+ d=not/
+ cd -- not/.
dash: 3: cd: can't cd to not/.
+ pwd -P
/tmp/chrome
+ printf ./%s\n\n not/
./not/

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.