ls -l для всех родительских каталогов - PullRequest
13 голосов
/ 21 июня 2020

Я хочу получить список всех разрешений для каталогов от текущей папки до /. Например, для каталога: /var/lib/program/subfolder мне нужен вывод, такой как:

$ 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

Меня не волнует порядок (от /var до /subfolder или наоборот) , количество жестких ссылок или даже дату. Я просто записал их для имитации вывода ls -l. Кроме того, мне все равно, как печатается каждое имя файла (/var и /lib, var и lib или /var и /var/lib). Меня просто интересует право собственности на каждый файл / каталог в пути от выбранного файла или от pwd до /.

В случае, если мне нужно установить какую-то программу, я использую Ubuntu 20.04.

Ответы [ 6 ]

7 голосов
/ 21 июня 2020

На этот вопрос уже был дан ответ на superuser.com (я не знаю, могу ли я отметить вопрос с одного сайта как дубликат с другого). Решение так же просто, как написать (при условии, что я нахожусь в том же каталоге, что и целевое имя файла):

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

Из-за -l в нем перечислены основные c разрешения в длинном формате для каждого родительского каталога. .

Мне нужно использовать pwd / realpath, потому что namei не разрешает относительные пути. Если меня нет в целевом каталоге, просто укажите полный путь.

5 голосов
/ 21 июня 2020

Я написал для вас сценарий bash. Если у вас есть место в именах, в нем будут ошибки. Если вас это беспокоит, я рад рекомендациям по изменениям в комментариях.

#!/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

С помощью realpath -s вы можете поймать абсолютный путь, но вы не будете переходить по ссылке. Если аргумент не указан, мы будем использовать pwd в качестве файла / каталога для списка.

Мы добавляем каждый путь в список. Это дает нам преимущество в виде лучшего макета в конечном итоге, так что мы получаем красивую таблицу, потому что мы запускаем ls только один раз.

Вывод:

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
4 голосов
/ 21 июня 2020

Я сделал этот небольшой скрипт, который делает это. Я использую cd "$1"; pwd, чтобы получить текущий каталог, чтобы пути не были канонизированы (скажем, если вы попробуете magic-ls . и ваш текущий каталог / var / lib / postgres, но это символическая ссылка на / mnt / postgres, вы получите /var, /var/lib и /var/lib/postgres, при использовании realpath вы получите /mnt и /mnt/postgres)

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

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

Вот пример вывода:

[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

Кстати, он также будет работать без аргументов, поскольку cd "" не изменяет ваш каталог.

Edit: удалено realpath из проверки while, так как это может привести к неожиданным результатам если в пути была ссылка на / и она не нужна.

2 голосов
/ 21 июня 2020

Просто используя расширение параметра:

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

метод вызова:

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

давая

-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
1 голос
/ 21 июня 2020
#! /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"

Терминальная сессия:

$ 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'
1 голос
/ 21 июня 2020

Это, возможно, должно сработать:

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

РЕДАКТИРОВАТЬ: Сначала я неправильно понял вопрос. Попробуйте это:

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

EDIT2: ответ fillipe, вероятно, лучший, но вот моя третья и последняя попытка, которая работает как с файлами, так и с каталогами:

magic_ls() {
fname="$1"
while true ; do
ls -lhd "$fname"
[[ "$fname" == "/" ]] && break ;
fname=$(dirname $(readlink -f "$fname"))
done
}
...