使用 find 对齐列以实现“ls -l”样式列表

使用 find 对齐列以实现“ls -l”样式列表

我正在尝试实现与ls -l使用 时获得的列表格式相同的格式find。尽管末尾是完整路径名而不是文件名。 FWIW我正在使用find (GNU findutils) 4.5.11.

我找到了该-ls标志,这很好,但它的列间距比 多得多ls -l,这没有用,特别是在末尾有完整路径名,因为它很可能将结果推到两行并使得阅读它们很困难。例如...

$ find /example -ls
  7439    4 -rwxrwxr-x   1 example    example        1579 Oct 26  1985 /path/to/first/file/that/was/found
   530    4 -rwxrwxr-x   1 example    example         122 Oct 26  1985 /path/to/second/file/that/was/found

因此,虽然这已经完成了工作,但我想做得更好。看看-printf的标志find,似乎可以实现同样的目标。到目前为止,我已经拥有了-printf '%M %u %g %p\n'很棒的信息,我可以自定义我想要的信息并将其他信息添加到其中。但...

问题是,如何对齐列?

当用户名和组名的长度不同时,这种方法就不太有效。例如...

$ find /example -printf '%M %u %g %p\n'
-rwxr-xr-x root root /path/to/first/example/file
-rwxr-xr-x example example /path/to/second/example/file

我该如何解决这个问题?最好只使用find,但如果不可能的话,通过管道传输到其他东西也可以。的手册页find似乎没有任何使用此选项-printf

答案1

-printfGNU 中的格式说明符find采用宽度和对齐(等)限定符,就像printf()C 函数一样,这意味着您可以向左或向右对齐数据,并且对于当前项目来说至关重要的是,为数据分配一定的宽度。

默认输出:

$ find . -printf '%M %u %g %p\n'
drwxr-xr-x kk wheel .
-rw-r--r-- kk wheel ./.zshrc
-rw-r--r-- kk wheel ./file
drwxr-xr-x root wheel ./rootstuff
-rw-r--r-- root wheel ./rootstuff/SECRET
-rw------- kk wheel ./.viminfo

指定用户和组列的宽度 (6)(右对齐):

$ find . -printf '%M %6u %6g %p\n'
drwxr-xr-x     kk  wheel .
-rw-r--r--     kk  wheel ./.zshrc
-rw-r--r--     kk  wheel ./file
drwxr-xr-x   root  wheel ./rootstuff
-rw-r--r--   root  wheel ./rootstuff/SECRET
-rw-------     kk  wheel ./.viminfo

相同,但左对齐:

$ find . -printf '%M %-6u %-6g %p\n'
drwxr-xr-x kk     wheel  .
-rw-r--r-- kk     wheel  ./.zshrc
-rw-r--r-- kk     wheel  ./file
drwxr-xr-x root   wheel  ./rootstuff
-rw-r--r-- root   wheel  ./rootstuff/SECRET
-rw------- kk     wheel  ./.viminfo

文件大小以字节为单位,分配 5 位数字(用零填充,因为只是显示如何完成):

$ find . -printf '%M %-6u %-6g %05s %p\n'
drwxr-xr-x kk     wheel  00512 .
-rw-r--r-- kk     wheel  00000 ./.zshrc
-rw-r--r-- kk     wheel  00095 ./file
drwxr-xr-x root   wheel  00512 ./rootstuff
-rw-r--r-- root   wheel  00000 ./rootstuff/SECRET
-rw------- kk     wheel  00922 ./.viminfo

请注意,该ls命令很可能根据实际需要为其列动态分配宽度,而您的find -printf命令必须使用静态宽度,除非您运行find两次以首先计算每列所需的空间,然后再次实际格式化输出(此这就是为什么find -ls输出如此宽的原因,它不使用两遍方法,而是只为每一列提供足够的空间,希望一切都能很好地对齐)。


当然,如果您没有数千个文件,并且您只想列出所有内容,递归地(即,您不需要对 中找到的路径名进行过滤或执行其他操作find),您可以只使用ls

$ ls -d -l **/*
-rw-------  1 kk    wheel  922 Jul 25 23:46 .viminfo
-rw-r--r--  1 kk    wheel    0 Jul 19 23:39 .zshrc
-rw-r--r--  1 kk    wheel   95 Jul 25 23:51 file
drwxr-xr-x  2 root  wheel  512 Jul 26 00:00 rootstuff
-rw-r--r--  1 root  wheel    0 Jul 26 00:00 rootstuff/SECRET

这依赖于**可用的通配模式,默认情况下,它在zshshell 中,bash如果您使用shopt -s globstar.它还依赖于 shell 匹配隐藏名称。如果您使用和来设置该选项, shellzsh将执行此操作。GLOB_DOTSsetopt GLOB_DOTSbashshopt -s dotglob

如果您的通配模式扩展到列表太长以致于生成“参数列表太长”错误,则此方法将不起作用。

此输出与普通输出不同,ls -l -R因为目录不会单独列出且目录之间有分隔符。

答案2

这是另一个简单的替代方案

$ find example -exec ls -ld {} +

相关内容