使用管道而不使用 ls-lS 命令对列表进行排序

使用管道而不使用 ls-lS 命令对列表进行排序

Linux 程序“sort”可以对文件或另一个程序的输出进行排序。如何使用 sort 按 1) 文件名 2) 文件大小对 ls 命令的输出进行排序。

我知道“ls”命令有一些选项可以执行此操作,但我尝试使用这样的排序:“ls”命令显示大小,“sort”命令选项控制排序,然后使用管道。

我怎样才能实现这个目标?

答案1

GNU 实现stat1,并假设文件名不包含换行符,并且-当前目录中没有调用任何文件

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 分隔的记录,因此无法工作,因为换行符与文件名中的任何字符一样有效。

你不能使用\0in 来获得 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
  • GNUfind及其-printf谓词
  • zsh、BSD 或 GNU stat(具有不兼容的 API)
  • 或者更高级的编程语言,例如 perl、ruby 或 python 及其stat()// ... API 和内置排序工具。lstat()statx()

相关内容