使用 ls 命令列出目录中的文件时难以执行复杂的排序

使用 ls 命令列出目录中的文件时难以执行复杂的排序

我所寻求的行为是使用 ls 命令进行嵌套排序,其中一种方法的排序不会抵消第二种方法的排序。确切的期望行为本质上是:

首先按目录排序,然后按文件排序,再加上一些美观和可读性的选项:

ls --group-directories-first -pAN -I ".*"

然后,无需撤消此排序,对目录下列出的所有文件应用分组扩展:

ls -X

然后,仅在每个扩展子组内按字母顺序对每个文件进行排序,数字的排序方式与你计数时的排序方式相同(例如 0,001,01,1..9,10,11..99,100..,A01,Ab,a,ab):

ls -v

不幸的是,ls -Xv它不会先应用一种排序,而是导致 -v 选项抵消 -X 选项。一种排序不会抵消另一种排序的一个例子是,ls --group-directories-first -v首先列出的目录优先,然后使用 -v 选项按版本排序,而不会覆盖目录在文件之前的排序优先级。

我正在寻找的行为的具体说明在示例目录中如下:

aDirectory/
a01Directory/
Bdirecory/
b/
0
01
1
9
0010
010
10
100
101
Afile
aFile
afilE
afile
B01
B01a
Ba01
Ba 01
BA 02
Ba02
Ba 02
1.jpg
9.jpg
010.jpg
10.jpg
A.jpg
a.jpg
a01.jpg
a01 today.jpg
B.jpg
b.jpg
AnotherFile.txt
another01File.txt
another 01 File.txt
another File.txt
another File01.txt
Z.txt

如果 -X 和 -v 彼此不冲突,则其等效于此命令:

ls --color=auto --group-directories-first -pANXv -I ".*"

我尝试过使用 ls 的不同选项组合,使用不同的选项将 ls 导入 sort 命令,以及使用正则表达式将 ls 导入 egrep。我会用 C 和 bashscript 编程,因此编写脚本或程序的技巧是一个完美的解决方案。

答案1

这应该可行。首先是简化版本(文件名中有空格时可能会出错,尤其是文件扩展名中有空格的情况)

ls -p |
  awk -F. '{ if ($0 ~ /\/$/ ) { print "!",$0 } else if ( NF == 1 ) { print "!!",$0 } else { print $NF,$0 } }' |
  sort -k 1,1 -k 2,2V | cut -d' ' -f2-

高级版本可以处理空格并包含额外的 ls 选项

ls --color=auto -pANXv -I ".*" |
  awk -F. 'BEGIN {OFS="/"} { if ($0 ~ /\/$/ ) { print "\001",$0 } else if ( NF == 1 ) { print "\001\001",$0 } else { print $NF,$0 } }' |
  sort -t/ -k 1,1 -k 2,2V |
  cut -d/ -f2-

怎么运行的

  • ls部分应该很清楚。--group-directories-first这里不需要选项。

  • awk命令将文件名拆分为.以下三项操作之一

    1. 如果行以 a 结尾,则/它被识别为目录(这就是为什么选项-p至关重要ls),awk 将打印一个“1”字节、字符OFS(第一个例子中的空格,这就是为什么它!在前面打印 a 的原因)最后是完整的目录名称
    2. 如果 name 没有.,即没有文件扩展名,awk 将打印两个“1”字节(或!!简单版本),OFS字符和完整的文件名
    3. 如果名称有.awk 将打印文件扩展名(最后一个之后的所有内容.)、OFS字符并再次打印完整文件名(包括文件扩展名,但这并不重要)
  • 因此在awk输入类似

    directory/
    plain
    test.txt
    archive.tar.gz
    

    将被转换为(我使用 ␁ 来可视化“1”字节)

    ␁/directory/
    ␁␁/plain
    txt/test.txt
    gz/archive.tar.gz
    
  • 将对sort除以 ␟ 的两个字段分别进行排序。第一个字段按正常方式排序,第二个字段使用 版本排序(V中的-k 2,2V)。

  • 只需cut删除第一个字段,即按扩展分组的排序助手。

请注意,我尚未进一步测试(Unicode)排序区域设置的影响。之所以选择“1”字节,是因为它在大多数情况下应该首先排序,并且其中一个应该在两个之前排序。

PS:我首先尝试为您构建具有稳定功能的程序sort,但首先,我无法保证它是否真的像某些人期望的那样稳定,并且它不适用于具有 的目录.或具有多个 的文件.。并且所需的https://stackoverflow.com/questions/3222810/sorting-on-the-last-field-of-a-line而是让我找到了当前的解决方案。

ls --group-directories-first -v | sort --stable --field-separator=. --key=2

PPS:-A加号-I ".*"是一个奇怪的组合。它们不是互相抵消了吗?

相关内容