9

I have a file path.. Is there any single command to see the file/directory permissions of all the intermediate directories in the path..?

0

6 Answers 6

12

Linux comes with the namei command which is mainly useful to display symbolic links in paths, but can also show ownership.

$ namei -nom ~   
f: /home/gilles
 drwxr-xr-x root   root   /
 drwxr-sr-x root   staff  home
 drwxr-xr-x gilles gilles gilles

Otherwise, here's a way to iterate over the successive directories containing a given file (not the only one, as other answers on this page illustrate) and list their contents.

d=$PWD; set /;
while [ -n "$d" ]; do set -- "$@" "$d/"; d=${d%/*}; done;
ls -ld "$@"

Note that this listing can be a little misleading in the presence of symbolic links. For example, if /foo/bar is a symbolic link to /hello/world which is itself a symbolic link to /one/two, and all of /foo, /hello and /world are world-readable (say mode 755) but /hello is not readable to user Alice, then Alice won't be able to reach /foo/bar, yet the listing above will show only world-readable directories.

10

Here are two oneliners. One ls call per path component:

$ (IFS=/; set -f -- $PWD; for arg; do path="${path%/}/$arg"; ls -dal "$path"; done)

Output:

# drwxr-xr-x  31 root  admin  1122  4 Nov 22:08 /
# drwxr-xr-x  9 root  admin  306  3 Nov 17:36 /Users
# drwxr-xr-x+ 67 janmoesen  staff  2278  7 Nov 14:46 /Users/janmoesen
# drwxr-xr-x+ 53 janmoesen  staff  1802  4 Nov 22:07 /Users/janmoesen/Sites
# drwxr-xr-x  28 janmoesen  staff  952  7 Nov 15:01 /Users/janmoesen/Sites/example.com

With just one call to ls with all paths:

$ (IFS=/; set -f -- $PWD; for arg; do path="${path%/}/$arg"; paths+=("$path"); done; ls -dal "${paths[@]}")

Output:

# drwxr-xr-x  31 root       admin  1122  4 Nov 22:08 /
# drwxr-xr-x   9 root       admin   306  3 Nov 17:36 /Users
# drwxr-xr-x+ 67 janmoesen  staff  2278  7 Nov 14:46 /Users/janmoesen
# drwxr-xr-x+ 53 janmoesen  staff  1802  4 Nov 22:07 /Users/janmoesen/Sites
# drwxr-xr-x  28 janmoesen  staff   952  7 Nov 15:01 /Users/janmoesen/Sites/example.com
1
  • Thanks for the correction, Gilles! Could you give an example of how globbing can mess up the set -- without -f? I tried with a directory a[bar] on the same level as directories ab, aa and ar, but did not succeed. (EDIT: Succeed in failing, that is. I want to know how it goes wrong.)
    – janmoesen
    Commented Nov 10, 2011 at 7:43
1
#!/bin/bash

(( $# )) || set -- "$PWD"

IFS='/'
for _arg; do
    if ! [[ -e "${_arg}" ]]; then
        printf '%s\n' "${_arg} does not exist!"
        exit 1
    fi

    read -ra _dirs <<< "${_arg}"
    (( _length = ${#_dirs[@]} + 1 ))
    for (( _offset = 2 ; _offset < _length ; _offset++ )); do
        _current_dir="${_dirs[*]::_offset}"
        _perms=$(ls -ld "${_current_dir}" | awk '{ print $1" "$3" "$4 }')
        printf '%s %s\n' "${_perms}" "${_current_dir}"
    done
done
0

I don't know of a short way to do so. For this task I use a shell script, you may find useful, too:

 #!/bin/ksh

 if [ $# -eq 0 ]
  then
    set "$PWD"
  fi

 for path in "$@"
  do
   while true
    do
     ls -ld "$path"
     if [ -z "$path" -o "$path" = . -o "$path" = / ]
      then
        break
      fi
     path=$(dirname "$path")
    done
  done

EDIT: Using an until loop omits the need for the break ...

 #!/bin/ksh

 [ $# -eq 0 ] && set "$PWD"

 for path
  do
   until test -z "$path" -o "$path" = . -o "$path" = /
    do
     ls -ld "$path"
     path=$(dirname "$path")
    done
  done
3
  • Your script will break on certain paths with special characters.
    – Chris Down
    Commented Nov 7, 2011 at 13:36
  • ok - added some more quotes. But for such rare occasions and no changes made to anything I lived with that.
    – ktf
    Commented Nov 7, 2011 at 15:56
  • 1
    It would be simpler to leverage IFS for splitting on /, like janmoesen does. Commented Nov 7, 2011 at 23:24
0

Not so complicated, but this would help you I guess.

find . -type d -exec ls -lrt {} \;
0

List permissions of every directory in a directory path (up or down)

alias dirls='_dirls() { path="$(realpath $1)";_path="";for i in " " ${path//\// }; do _path="$_path$i/"; ls -ld $_path; done; unset _path; };_dirls'

alias dirls2='_dirls2() { path="$(realpath $1)"; while [[ "$path" != "/" ]]; do ls -ld "$path"; path="$(dirname "$path")"; done; ls -ldh /; };_dirls2'

eg:

# dirls /usr/local/bin
dr-xr-xr-x. 18 root root 236 Nov 11 19:01 /
drwxr-xr-x. 15 root root 181 Dec  7 11:50 /usr/
drwxr-xr-x. 15 root root 205 Nov 22 14:06 /usr/local/
drwxr-xr-x. 2 root root 4096 Dec  5 12:19 /usr/local/bin/

# dirls2 /usr/local/bin
drwxr-xr-x. 2 root root 4096 Dec  5 12:19 /usr/local/bin
drwxr-xr-x. 15 root root 205 Nov 22 14:06 /usr/local
drwxr-xr-x. 15 root root 181 Dec  7 11:50 /usr
dr-xr-xr-x. 18 root root 236 Nov 11 19:01 /

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