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.
    – choroba
    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.

Not the answer you're looking for? Browse other questions tagged .