我需要生成所有文件和目录及其权限和所有者的列表,例如
-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
,我建议使用stat
with--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}