Linux 程序“sort”可以对文件或另一个程序的输出进行排序。如何使用 sort 按 1) 文件名 2) 文件大小对 ls 命令的输出进行排序。
我知道“ls”命令有一些选项可以执行此操作,但我尝试使用这样的排序:“ls”命令显示大小,“sort”命令选项控制排序,然后使用管道。
我怎样才能实现这个目标?
答案1
和GNU 实现stat
1,并假设文件名不包含换行符,并且-
当前目录中没有调用任何文件
stat -c '%s %n' -- * | sort -t' ' -k1,1n -k2
排序键:
- 首先按字段 1(大小)按数字排列(升序)
- 接下来按字段 2-end(文件名)词汇(升序)
¹ 注意stat
不是标准命令,并且存在几个不兼容的实现
答案2
类 Unix 系统上的文件名是一个或多个(通常达到一定限制)字节的序列,除了 0 和编码/
.
sort
对行进行排序,即 0 或更多的数组(在某些实现中达到一定限制)人物其他和换行符(以及某些实现的 NUL)基于命令行上给出的排序键规范。
(及其克隆)的 GNU 实现sort
可以处理输入上的 NUL,作为标准的扩展,并且还可以对 NUL 分隔的记录而不是行进行排序(使用选项-z
)。
C
如果您将语言环境修复为(实际上,如果您禁用本地化),则可以拥有字节==字符映射。
ls
例如,ast-open 的实现可以让你接近:
ls --format='%(size)d\t%(name)s'
但是,这是换行符分隔的记录,而不是 NUL 分隔的记录,因此无法工作,因为换行符与文件名中的任何字符一样有效。
你不能使用\0
in 来获得 NUL,但你可以这样做:
ls --format='%(size)d\t%(name)s/'
在 GNU 的帮助下awk
,您可以将这些/<newline>
分隔符转换为 GNU 的 NUL 分隔符sort -z
:
ls --format='%(size)d\t%(name)s' |
LC_ALL=C gawk -v 'RS=/\n' -v 'ORS=\0' 1 |
LC_ALL=C sort -zn |
LC_ALL=C tr '\0' '\n'
(tr
最终仅供展示)。
使用 GNU ls
,您无法像使用 ast-open 那样格式化输出(find
或者stat
是在 GNU 工具箱中执行此操作的工具),但从版本 9.0 开始,您可以使用该--zero
选项来输出以 NUL 分隔的记录。
和:
LC_ALL=C ls -go --zero
您会得到如下输出:
<mode><spaces><links><spaces><size><space><t1><spaces><t2><spaces><t3><space><name><NUL>
所以你可以从中提取大小和名称。
但这并不适用于所有类型的文件。
- 对于符号链接,
<name>
您会得到<name><space>-><space><target-path>
<size>
对于设备文件,您将获得<major>,<spaces><minor>
设备编号,而不是。
GNUls
还有一个--dired
选项,可以提供用于 的输出emacs
,以及有关每个文件名在输出中的开始和结束位置的信息。这对符号链接有帮助,但对设备文件没有帮助,并且您需要额外的工作来使用//DIRED//
偏移量来额外信息并将其重新格式化为适合排序的格式。
的输出ls
根本不意味着要进行后处理。
相反,您可以使用:
zsh
可以用任意标准排序的 glob- GNU
find
及其-printf
谓词 - zsh、BSD 或 GNU
stat
(具有不兼容的 API) - 或者更高级的编程语言,例如 perl、ruby 或 python 及其
stat()
// ... API 和内置排序工具。lstat()
statx()