获取所有文件和目录及其权限和所有者的列表

获取所有文件和目录及其权限和所有者的列表

我需要生成所有文件和目录及其权限和所有者的列表,例如

-rw-rw-r--    black www-data     foo/
-rw-r--r--    black www-data     foo/foo.txt
-rw-rw-r--    black www-data     bar/
-rwxrwxr-x    black www-data     bar/foo.sh

我需要这个列表来将其与我遇到错误的另一个实例进行比较。

答案1

如果你有 GNU find,你可以使用它的printf操作:

find . -printf "%M %u %g %p\n"

这将列出当前目录和任何子目录中的所有文件,以及它们的类型和权限样式ls、所有者和组以及从当前目录开始的全名。

如果您想要一致的间距,可以使用字段宽度说明符,例如

find . -printf "%M %-20u %-20g %p\n"

您可以使用 输出选项卡\t

答案2

要获取 Linux 上单个文件或目录的信息,您可以使用stat具有自定义输出格式的实用程序:

$ stat -c '%A %U %G %n' ~/.bashrc
-rw-r--r-- myself myself /home/myself/.bashrc

如果您想要制表符分隔的输出,请用作$'%A\t%U\t%G\t%n'选项的参数-c(在理解$'...'为 C 字符串的 shell 中)。

要递归地获取当前目录及以下目录中所有内容的信息,请使用find

find . -exec stat -c $'%A\t%U\t%G\t%n' {} +

在 BSD 系统(任何免费系统和 macOS)上,您将需要使用stat -f '%Sp %Su %Sg %N'它(每个都S表示“符号”输出而不是数字)。在那里,您还可以使用%t插入选项卡:

find . -exec stat -f '%Sp%t%Su%t%Sg%t%N' {} +

在 macOS 上运行的示例:

$ tree
.
├── dir1
│   └── file
└── dir2
    └── othername

3 directories, 2 files
$ find . -exec stat -f '%Sp%t%Su%t%Sg%t%N' {} +
drwxr-xr-x  myself  staff   .
drwxr-xr-x  myself  staff   ./dir2
-rw-r--r--  myself  staff   ./dir2/othername
drwxr-xr-x  myself  staff   ./dir1
-rw-r--r--  myself  staff   ./dir1/file

答案3

为了独立于有时动态变化的输出格式ls,我建议使用statwith--printf选项来控制输出格式。下面将以更“机器可读”的格式创建这样一个列表,使用符号|作为分隔符(选择是任意的,有关更多信息,请参阅最后一段):

stat --printf="%A|%U|%G|%n\n" /path/to/dir/* > list_of_tiles.psv

这将以以下形式输出文件和属性的列表

-rw-rw-r--|black|www-data|foo.txt
drw-rw-r--|black|www-data|bar/

但是,默认情况下不会列出子目录中的文件和目录。为了实现这一目标,有几种方法:

  • 如果您使用的是 bash,则可以启用该globstar选项以允许递归作用的通配符模式:

    shopt -s globstar
    stat --printf="%A|%U|%G|%n\n" /path/to/dir/** > list_of_tiles.psv
    

    带输出

    drwxr-xr-x|mygroup|myuser|subdir1
    -rw-r--r--|mygroup|myuser|subdir1/subfile1.txt
    -rw-r--r--|mygroup|myuser|subdir1/subfile2.txt
    drwxr-xr-x|mygroup|myuser|subdir2
    -rw-r--r--|mygroup|myuser|subdir2/subfile3.txt
    -rw-r--r--|mygroup|myuser|that_file.txt
    -rw-r--r--|mygroup|myuser|this_file.txt
    
  • 否则,您可能需要求助于 GNU find

    find . -printf '%M|%g|%u|%p\n'
    

    带输出

    drwxr-xr-x|mygroup|myuser|.
    drwxr-xr-x|mygroup|myuser|./subdir1
    -rw-r--r--|mygroup|myuser|./subdir1/subfile1.txt
    -rw-r--r--|mygroup|myuser|./subdir1/subfile2.txt
    drwxr-xr-x|mygroup|myuser|./subdir2
    -rw-r--r--|mygroup|myuser|./subdir2/subfile3.txt
    -rw-r--r--|mygroup|myuser|./that_file.txt
    -rw-r--r--|mygroup|myuser|./this_file.txt
    
  • 如果两者都不可用,则这是两者的组合:

    find . -exec stat --printf="%A|%U|%G|%n\n" {} \;
    

另请注意,如果文件名本身不包含分隔符|或换行符(不幸的是也允许使用字符),则此方法仅能真正成功地实现(自动?)比较的目的。这也是不鼓励的原因之一解析输出ls 或者find通过脚本。这同样适用于分隔符的任何选择;这个答案|之所以使用,是因为它在文件名中的出现频率低于空格等。

答案4

shellzsh具有数组比较运算符和stat用于检索文件元数据的内置函数(自 1996 年以来,因此早stat于 2000 年代初的 GNU 和 BSD)。

在那里你可以做:

zmodload zsh/stat
details=()
for f ($dir/**/*(DN)) stat -LsH s -- $f && details+="$s[mode] $s[uid] $s[gid] $f:t"

一旦获得两个数组中两个单独目录的结果(例如$details1和 )$details2,您可以执行以下操作:

print -rC1 'Only in first:' ${details1:|details2}
print -rC1 'Only in second:' ${details2:|details1}
print -rC1 'In both:' ${details1:*details2}

相关内容