我正在尝试实现与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
-printf
GNU 中的格式说明符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
这依赖于**
可用的通配模式,默认情况下,它在zsh
shell 中,bash
如果您使用shopt -s globstar
.它还依赖于 shell 匹配隐藏名称。如果您使用和来设置该选项, shellzsh
将执行此操作。GLOB_DOTS
setopt GLOB_DOTS
bash
shopt -s dotglob
如果您的通配模式扩展到列表太长以致于生成“参数列表太长”错误,则此方法将不起作用。
此输出与普通输出不同,ls -l -R
因为目录不会单独列出且目录之间有分隔符。
答案2
这是另一个简单的替代方案
$ find example -exec ls -ld {} +