Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

`ls -l` for all parent directories

Tags:

linux

bash

ls

I want to get a list of all directory permissions from current folder to /. For example, for the directory: /var/lib/program/subfolder, I want an output such as:

$ pwd
/var/lib/program/subfolder
$ magic_ls_-l_command somefile
drwxr-xr-x 10 root root 4096 May 15 20:20 var
drwxr-xr-x 10 root root 4096 May 15 20:20 lib
drwxrwxr-x 10 root user 4096 May 16 20:21 program
drwxrwxr-x 10 root user 4096 May 16 20:21 subfolder
-rwxrwxr--  1 root user 4096 May 16 20:22 somefile

I don't care about the order (from /var to /subfolder or the other way around), the number of hard links or even the date. I just wrote them down to emulate the ls -l output. Also, I don't care how each filename in printed (/var and /lib, var and lib, or /var and /var/lib). I'm just interested in the ownership of each file/directory in the path from the choosen file or pwd to /.

In case I should install some program, I'm under Ubuntu 20.04.

like image 420
Peregring-lk Avatar asked Jun 21 '20 16:06

Peregring-lk


6 Answers

This question has already been answered in superuser.com (I don't know if I can mark a question from one site as duplicate from another). The solution is as simple as writing (assuming I am in the same directory as the target filename):

$ namei -l $(pwd)/somefile   ## or `namei -l $(realpath -s somefile)`

Because of -l, it lists basic permissions in long format for each parent directory.

I have to use pwd/realpath because namei doesn't resolve relative paths. If I'm not in the target directory, just write the full path.

like image 151
Peregring-lk Avatar answered Oct 16 '22 08:10

Peregring-lk


I made this small script that does this. I use cd "$1"; pwd to get the current directory so that paths are not canonicalized (say, if you try magic-ls . and your current directory is /var/lib/postgres, but that is a symlink to /mnt/postgres, you will get /var, /var/lib and /var/lib/postgres, while using realpath you would get /mnt and /mnt/postgres)

magic-ls() {
    local current=$(cd "$1"; pwd)

    while [[ $current != '/' ]]; do
        ls -ld "$current"
        current=$(dirname "$current")
    done
}

Here's an example output:

[leodag@desk ~]$ magic-ls
drwx------ 1 leodag leodag 2722 jun 21 13:49 /home/leodag
drwxr-xr-x 1 root root 18 mai  2  2019 /home

By the way it will also work with no argument since cd "" does not change your directory.

Edit: removed realpath from the while check, since that could lead to unexpected results if there was a link to / in the path, and was unneeded.

like image 24
Leonardo Dagnino Avatar answered Oct 16 '22 09:10

Leonardo Dagnino


I wrote a bash script for you. It'll have some bugs, if you have space in names. If it bothers you, I'm happy for changes recommendations in the comments.

#!/bin/bash
if [ ! -z "$1" ] && [ -e "$1" ]
then
 path=`realpath -s "$1"` # read argument as absolute path
else
 path="$PWD" # No valid argument, so we take pwd
fi
paths=""
while [ "$path" != / ];do
 paths+=" $path" 
 path=`dirname "$path"`
done
paths+=" $path" # Adding / to pathlist too 
ls -ld $paths

With realpath -s you can catch the absolute path, but you wont follow the link. If no argument is given, we will use pwd as the file/directory to list.

We append each path to a list. This gives us the advantage of a better layout in the end, so that we get a nice table because we run ls only once.

Output:

bobafit:~$ magic_ls_-l_command /usr/bin/python3
drwxr-xr-x 21 root root   4096 Jun 20 10:07 /
drwxr-xr-x 14 root root   4096 Sep  5  2019 /usr
drwxr-xr-x  2 root root 110592 Jun 20 10:07 /usr/bin
lrwxrwxrwx  1 root root      9 Apr  7 12:43 /usr/bin/python3 -> python3.8
like image 5
Boba Fit Avatar answered Oct 16 '22 09:10

Boba Fit


Just using parameter expansion:

#!/usr/bin/env bash
path="$1"
while test -n "$path"; do
    ls -lLd "$path"
    path="${path%/*}"
done

calling method :

bash test.sh /var/lib/program/subfolder/somefile

giving

-rw-r--r-- 1 root root 0 Jun 21 18:49 /var/lib/program/subfolder/somefile
drwxr-xr-x 1 root root 4096 Jun 21 18:49 /var/lib/program/subfolder
drwxr-xr-x 1 root root 4096 Jun 21 18:49 /var/lib/program
drwxr-xr-x 1 root root 4096 Jun 21 18:49 /var/lib
drwxr-xr-x 1 root root 4096 Jun 13 19:24 /var
like image 3
Philippe Avatar answered Oct 16 '22 08:10

Philippe


#! /bin/bash

cur=""
IFS="/"
path=`pwd`

for dir in ${path:1}
do
        cur=$cur/$dir
        ls -lhd "$cur"
done

cur=$cur/$1
ls -lhd "$cur"

Terminal Session:

$ pwd 
/tmp/dir_underscore/dir space/dir special @!)
$ ls 
bash.sh  test.txt
$ ./bash.sh test.txt
drwxrwxrwt 28 root root 36K Jun 21 22:45 /tmp
drwxr-xr-x 3 root root 4.0K Jun 21 22:27 /tmp/dir_underscore
drwxr-xr-x 3 root root 4.0K Jun 21 22:28 '/tmp/dir_underscore/dir space'
drwxr-xr-x 2 root root 4.0K Jun 21 22:54 '/tmp/dir_underscore/dir space/dir special @!)'
-rw-r--r-- 1 root root 0 Jun 21 22:29 '/tmp/dir_underscore/dir space/dir special @!)/test.txt'
like image 1
m0hithreddy Avatar answered Oct 16 '22 08:10

m0hithreddy


This should possibly work:

pwd ; ls -lh ; while true ; do  cd .. ; pwd ; ls -lh ; [[ "$PWD" == "/" ]] && break ; done

EDIT: I misunderstood the question at first. Try this:

(pwd ; ls -ldh ; while true ; do cd .. ; pwd ; ls -ldh ; [[ "$PWD" == "/" ]] &&
break ; done ; cd "$START")

EDIT2: fillipe's answer is probably the best, but here's my third and last attempt, which works on both files and directories:

magic_ls() {
fname="$1"
while true ; do
ls -lhd "$fname"
[[ "$fname" == "/" ]] && break ;
fname=$(dirname $(readlink -f "$fname"))
done
}
like image 1
JMW Avatar answered Oct 16 '22 09:10

JMW