Super User is a question and answer site for computer enthusiasts and power users. 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

In a given shell script I need to take a known path and check it upwards (to the file system root) for correct permissions. How would I split the path and walk upwards in a shell script (can be bash or a "lower common denominator")?

share|improve this question
up vote 0 down vote accepted

This should work:

unset path
parts=$(pwd | awk 'BEGIN{FS="/"}{for (i=1; i < NF; i++) print $i}')

for part in $parts
ls -ld $path   # do whatever checking you need here
share|improve this answer
Thanks, that works. Is there a (ba)sh-only solution? – k-fish Nov 5 '09 at 21:12

When I tried ennuikiller's awk solution, it missed the current directory for me.

So, while a bit late, here's a bash-only solution:

while [ "$foo" != "" ]; do
    echo $foo # work with directory here

Don't know if it's the most elegant solution, but it works. I found a simple explanation of the string manipulation on tldp and wrapped a loop around it.

share|improve this answer

To expand on ennuikiller's solution:

realpath () {
    # realpath()        -- print absolute path (os.path.realpath) to $1
    #                      note: OSX does not have readlink -f
    python -c "import os,sys; print(os.path.realpath(os.path.expanduser(sys.argv[1])))" "${1}"

walkpath () {
    # walkpath()        -- walk down path $1 and $cmd each component
    #   $1 : path (optional; default: pwd)
    #   $2 : cmd  (optional; default: ls -ald --color=auto)
    if [ $(uname) == "Darwin" ]; then
        cmd=${2:-"ls -ldaG"}
        cmd=${2:-"ls -lda --color=auto"}
    dir=$(realpath ${dir})
    parts=$(echo ${dir} \
        | awk 'BEGIN{FS="/"}{for (i=1; i < NF+2; i++) print $i}')
    unset path
    for part in $parts; do
        paths=("${paths[@]}" $path)
    ${cmd} ${paths[@]}
share|improve this answer

In Bash with the path given in a shell variable (e.g. $DIR) you can always obtain the last (lowest) path component using the basename command and the remaining path up with the dirname command:

LAST="$( basename "$DIR" )"
DIR=""$( dirname "$DIR" )"

results in $DIR=/home/user/mail/work and $LAST=spam

But why use variables when you can simply walk up the path itself:

while [ "/" \!= $(pwd) ] ; do
    (chmod|setfacl|do_anything) .
    cd .. ;
share|improve this answer

On Linux you can use the utility namei which is included in util-linux to list the standard Unix permissions:

namei -v path

Below is another script which does not contain bashisms and should run in any modern Bourne-like shell. For decomposing of the path it uses the standard command dirname to gradually strip the last component off until / or . rests (and the path does not change any further). Just put any code instead of ls -ld to perform on all components of the path (e.g. getfacl).


while test "$f" != "$p" ; do
    ls -ld "$f"
    f="$(dirname "$f")"
share|improve this answer

Your Answer


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.