32

There's a command, I think it comes with apache, or is somehow related to it, that checks permissions, all the way down. So if I have /home/foo/bar/baz it will tell me what the permissions are for baz, bar, foo, and home. Does anyone know what this command is or another way of doing this? The command basically starts at the argument, and works it's way up to / letting you know what the permissions are along the way so you can see if you have a permission problem.

6 Answers 6

37

The utility you may be thinking of is the namei command. According to the manual page:

Namei uses its arguments as pathnames to any type of Unix file (symlinks, files, directories, and so forth). Namei then follows each pathname until a terminal point is found (a file, directory, char device, etc). If it finds a symbolic link, we show the link, and start following it, indenting the output to show the context.

The output you desire can be received as follows:

$ namei -l /usr/src/linux-headers-2.6.35-22/include/
f: /usr/src/linux-headers-2.6.35-22/include/
drwxr-xr-x root root /
drwxr-xr-x root root usr
drwxrwsr-x root src  src
drwxr-xr-x root root linux-headers-2.6.35-22
drwxr-xr-x root root include

The namei command is part of the linux-util-ng software package. See the manual page for more details.

7
  • it might be, seems it only does it for symlinks, though I don't remember what I was using and whether it was on a symlink. Jan 16, 2011 at 4:16
  • While I saw older manual pages that only mentioned symlinks, as both my example and the man page show, it words for all types of files and directories.
    – Steven D
    Jan 16, 2011 at 9:00
  • not for me :( it long gives a long listing like that, for me, with symlinks. Jan 20, 2011 at 14:43
  • what version are you using? I'm using 2.18 Jan 20, 2011 at 14:44
  • 2
    another useful way to use namei for those who are lazy. namei -l $PWD/public_html/ From your current dir us $PWD to get the list of perms up to your current dir.
    – nelaaro
    Feb 22, 2015 at 13:27
8

I'm not aware of any commands, but it is quite easy to write a script:

#!/bin/bash    
ARG=$1
while [[ "$ARG" != "." && "$ARG" != "/" ]]
do
        ls -ld -- "$ARG"
        ARG=`dirname -- "$ARG"`      
done

Example:

$ perms.sh /tmp/1/2/3/hello.txt

-rw-rw-r--    1 user    group          0 Jan 14 16:59 /tmp/1/2/3/hello.txt
drwxrwxr-x    2 user    group       4096 Jan 14 16:59 /tmp/1/2/3
drwxrwxr-x    3 user    group       4096 Jan 14 16:43 /tmp/1/2
drwxrwxr-x    3 user    group       4096 Jan 14 16:43 /tmp/1
drwxrwxrwt   12 root     root       4096 Jan 14 17:02 /tmp
3

I think the command you where looking for is:

namei -l `pwd`

which, when executed in /tmp/foo/bar, gives you a listing like:

drwxr-xr-x root   root   /
drwxrwxrwt root   root   tmp
drwxr-xr-x user   group  foo
drwxr-xr-x user   group  bar
2

How about a recursive bash function for a fun solution:

[bash#] function uptree { ( \ls -ld -- "$PWD"; [ "$PWD" = '/' ] && return; cd ..; uptree ) | column -t ; } 

[bash#] pwd
/home/frielp/bin/dev

[bash#] uptree
drwxrwxr-x.  2   frielp  frielp  4096  Dec  14  14:50  /home/frielp/bin/dev
drwxr-xr-x.  15  frielp  frielp  4096  Aug  23  10:48  /home/frielp/bin
drwxr-xr-x.  60  frielp  frielp  4096  Jan  14  16:48  /home/frielp
drwxr-xr-x.  4   root    root    4096  Dec  1   09:14  /home
dr-xr-xr-x.  23  root    root    4096  Jan  14  08:18  /

[bash#] pwd
/home/frielp/bin/dev
[bash#] 
1
  • This is my favorite because it requires no dependencies. Might want to make it cd .. >/dev/null though for those of us with a $CDPATH set (which causes cd to output the current dir when it's used and that interferes with the output from your function.)
    – beporter
    Jun 4, 2014 at 17:03
1

This could easily be made a one-liner. This is not recursive and should be a relatively fast way of doing this in bash. Calling pwd in each loop isn't particularly fast, so avoid if you can.

#!/bin/bash
if [ -n "$1" ]; then
    echo "Usage: $0 [FILE]"
    exit 1
fi
cd -P -- "$1"
IFS="/"
set -f # turn off globbing for the expansion of $PWD below
for dir in $PWD; do
    stat -c "$PWD %A" .
    cd ..
done

Alternative, a one-liner for the current directory.

(IFS="/"; set -f; for dir in $PWD; do stat -c "$PWD %A" .; cd ..; done)
5
  • Is that a one-liner? Did I miss something?
    – phunehehe
    Jan 15, 2011 at 5:26
  • As a one-liner for the pwd: pushd $(pwd) >/dev/null; OIFS=$IFS; IFS="/"; for dir in $(pwd); do stat -c "$(pwd) %A" .; cd ..; done; IFS=$OIFS; popd >/dev/null
    – ewindisch
    Jan 15, 2011 at 5:33
  • Your script won't work with file names containing spaces or globbing characters. Jan 15, 2011 at 16:32
  • Gilles, I guess not. It had originally, but I mucked it up in editing. I've removed the xargs and it should work properly again.
    – ewindisch
    Jan 16, 2011 at 0:54
  • Why use pushd and popd? Or eval, for that matter? You can use a subshell (parentheses) to keep all changes local. You need double quotes to protect directory names with spaces, and set -f to turn off globbing. cd -P follows all symlinks. Jan 16, 2011 at 1:19
1

alternately, consider using find with tac

find /path -printf '%M %u %g %p\n' | tac

You must log in to answer this question.

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