鉴于以下文件:
ABC38388.SC01.StatueGrade_MKP
ABC38388.SC02.Statue_GKP
DEF38389.SC03.Statue_HKP
XYZ38390.SC00.Statue_WKP
我如何根据值列出它们SC
,如下所示:
XYZ38390.SC00.Statue_WKP
ABC38388.SC01.StatueGrade_MKP
ABC38388.SC02.Statue_GKP
DEF38389.SC03.Statue_HKP
答案1
在这种特殊情况下,您的文件名不包含任何空格或其他奇怪的字符,您可以使用ls
它并通过管道传输sort
:
$ ls -d -- *.SC* | sort -t. -k2
XYZ38390.SC00.Statue_WKP
ABC38388.SC01.StatueGrade_MKP
ABC38388.SC02.Statue_GKP
DEF38389.SC03.Statue_HKP
设置-t
字段分隔符并-k2
告知根据以第二个sort
字段开头的行部分进行排序(用于第二个字段-k2,2
仅有的)。
对于更复杂的情况,您可以打印每个文件名,后跟 NULL 字符 ( ),然后使用其选项通过\0
管道传递给 GNU以告诉它读取 NULL 分隔的行,最后使用将其更改回:sort
-z
tr
\0
\n
printf '%s\0' *SC* | sort -zt. -k2 | tr '\0' '\n'
答案2
oe
使用 zsh,您可以使用或glob 限定符定义自己的 glob 排序顺序o+
:
ls -lUd -- *(oe['REPLY=${REPLY#*.SC}'])
或者:
bysc() REPLY=${REPLY#*.SC}
ls -lUd -- *(o+bysc)
排序函数接收文件名,$REPLY
并返回一个字符串,$REPLY
该字符串将根据通配符进行排序。在这里,我们返回第一次出现 的右侧的文件名部分.SC
(如果不包含 ,则返回完整文件名.SC
)。
答案3
在 GNU 系统上并使用zsh
或bash
作为 shell,使用以下命令:
find -maxdepth 1 -type f -print0 | sort -z -t. -k3 | \
while IFS="" read -r -d "" f; do
basename "$f"
done
find
搜索当前目录 ( ) 中的文件-maxdepth 1
并以空字节分隔 (-print0
) 打印它们。sort
读取以空字节分隔 ( ) 的输入,并对以点 ( ) 分隔的-z
第三个字段 ( ) 开始的记录部分进行排序。-k3
-t.
while
读取输入- 并
basename
打印不带路径的名称
- 并
答案4
我会——就像我经常做的那样——建议perl
。
perl
有一个排序函数,可让您指定比较函数。此比较函数是采用两个值并返回或 的任何测试-1
,具体取决于相对位置。0
1
它迭代列表,将每个值设置为$a
和$b
并为每个元素“进行测试”。
所以默认情况下:
$a cmp $b
用于字符串比较或sort { $a <=> $b }
数字比较。
但因此,您可以应用任意复杂的自定义排序标准:
#!/usr/bin/perl
use strict;
use warnings;
sub sort_by_sc {
my ( $a_sc ) = $a =~ m/SC(\d+)/;
my ( $b_sc ) = $b =~ m/SC(\d+)/;
return $a_sc <=> $b_sc;
}
my @file_list = qw (
ABC38388.SC01.StatueGrade_MKP
ABC38388.SC02.Statue_GKP
DEF38389.SC03.Statue_HKP
XYZ38390.SC00.Statue_WKP
);
print sort sort_by_sc @file_list;
或者简化为一行,读取STDIN
或文件(换行符分隔,通常就足够了):
perl -e 'print sort {@x = map {/SC(\d+)/}($a,$b); $x[0] <=> $x[1]} <>'
glob
您可以改为向其提供目录模式的结果:
perl -e 'print sort {@x = map {/SC(\d+)/}($a,$b); $x[0] <=> $x[1]} glob ( "*SC*")'