所有父目录的 `ls -l`

14
我想获取从当前文件夹到/所有目录权限的列表。例如,对于目录:/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/libvarlib,或者 /var/var/lib)。我只对从所选文件或 pwd/ 路径上每个文件/目录的所有权感兴趣。
如果需要安装程序,我使用的是 Ubuntu 20.04。

除非您澄清了“somefile”路径中的某个路径组件是符号链接时的预期行为,否则几乎不可能在此问题上发布正确答案。 - oguz ismail
1
在符号链接的情况下,我想查看指向的文件或目录的权限。 - ABu
7个回答

8

这个问题已经在superuser.com中得到了回答(我不知道是否可以将一个站点的问题标记为另一个站点的重复)。解决方法非常简单,只需要输入以下命令即可(假设我与目标文件在同一目录下):

$ namei -l $(pwd)/某个文件   ## 或 `namei -l $(realpath -s 某个文件)`

由于使用了-l参数,它会以长格式列出每个父目录的基本权限。

我必须使用pwd/realpath,因为namei不会解析相对路径。如果我不在目标目录中,只需写入完整路径即可。


1
哇,直到今天才听说过它。 - oguz ismail
1
@oguzismail 是的,有很多不常见但非常有用的命令,比如 pstree - ABu
1
你可以用 $(realpath -s somefile) 替换 $(pwd)/somefile。使用 -s 参数将不会跟随符号链接。 - Boba Fit
@BobaFit namei 选项 -n 也不会跟随符号链接。 - ABu
1
这不是我考虑选择realpath的唯一原因,使用它可以解析整个路径,即使它不在您的工作目录中。 - Boba Fit
1
从未听说过namei,真的很酷。但是使用realpath -s的问题在于,如果符号链接是您调用它的文件/目录,则不会解析该符号链接,但仍将遵循父目录的符号链接。因此,例如,如果您在/home/leo/test/,而/home/leo是指向/mnt/leo的符号链接,则realpath -s .将给您/mnt/leo/test而不是/home/leo/test - Leonardo Dagnino

5
我为您写了一个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

5

我写了这个小脚本来实现这个功能,我使用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 ""不会更改你的目录。

编辑:从while检查中删除realpath,因为如果路径中有指向/的链接,则可能导致意外结果,并且是不必要的。


1
是的,如果$1不是目录,它将失败,我没有涵盖那种情况。ls -ld在这里确实打印符号链接。请记住,它将使用符号链接的绝对路径调用,也许您以另一种方式进行了测试? - Leonardo Dagnino
1
我的错,没错。 realpath会解除符号链接,但OP是否想要这样做并不清楚。 - oguz ismail
是的,如果路径中有指向“/”的链接,可能会导致意外的结果。我会进行更改。 - Leonardo Dagnino
1
你可以使用 realpath -s 命令来保留符号链接的路径。 - Boba Fit
我不知道 realpath -s,谢谢!在这种情况下,它基本上等同于变量本身,因为我只需要检查 /,所以我就这样留下了。 - Leonardo Dagnino

3

只需使用参数扩展:

#!/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
这可能有效:

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")

编辑2:fillipe的回答可能是最好的,但这是我第三次也是最后一次尝试,它适用于文件和目录:

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

1
我也曾经考虑过这样的方法。问题在于最终你不再处于你的目录中,而且你会得到该文件夹中所有文件的列表。你知道ls命令的-d选项吗?我是为了解决这个问题而学习它的。 - Boba Fit
Boba Fit,啊,我没有注意到它正在递归地打印目录。我会更新我的答案。 - JMW
哦,我一开始误解了你的问题。你只是想要指定路径中每个组件的权限。我会尽力而为。 - JMW

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

0

仅供参考。我的Mac没有namei命令(也许Homebrew有一个副本),但我想快速制作一个版本,使输出按照自上而下的顺序对齐。

#!/usr/bin/env bash
path="${1%/}"
DIRS=()
while test -n "$path"; do
  DIRS=( "$path" "${DIRS[@]}" )
  path="${path%/*}"
done
ls -ld "${DIRS[@]}"

示例输出:

$ lspath $TMPDIR
lrwxr-xr-x@   1 root  wheel    11 Oct  5  2018 /var -> private/var
drwxr-xr-x    7 root  wheel   224 Jul 16  2020 /var/folders
drwxr-xr-x@   3 root  wheel    96 Apr  5  2018 /var/folders/0c
drwxr-xr-x@   5 me    staff   160 Apr  5  2018 /var/folders/0c/2_s_qxd11m3d1smzqdrs3qg40000gp
drwx------@ 255 me    staff  8160 Oct  7 09:18 /var/folders/0c/2_s_qxd11m3d1smzqdrs3qg40000gp/T

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接