命令行按名称的一部分对文件或目录进行排序

命令行按名称的一部分对文件或目录进行排序

如何按名称的一部分(特别是括号中包含的元素或由定界符分隔的元素)对文件或目录进行排序?

我追求两个独立的解决方案,一个用于具有如下名称结构的目录:

Badger Bodger (2001)
Charlie Fisher's (1989)

以及以下格式的文件:

Could Be A Title.2001.prop.ext1
Another Potential Title.1989.prop.ext2

在这两种情况下,带有 1989 的目录或文件应该在 2001 之前。对于目录,排序依据元素在括号中。对于文件,它是分隔符后的前四位数字.

我在 Debian 8.0 上运行 bash。请寻找命令行解决方案。如果用 bash 编写,可以接受简短的脚本。

答案1

考虑以下文件:

$ ls  --quoting-style=c -1 *.*
"Another Potential Title.1989.prop.ext2"
"being there.2000.prop.ext3"
"Could Be A Title.2001.prop.ext1"
"Yet Another Potential Title.1989.prop.ext2"

按年份排序:

$ ls  --quoting-style=c *.* | sort -t. -k2n
"Another Potential Title.1989.prop.ext2"
"Yet Another Potential Title.1989.prop.ext2"
"being there.2000.prop.ext3"
"Could Be A Title.2001.prop.ext1"

对于您的目录,类似的方法也有效:

$ ls --quoting-style=c -d */ | sort -t'(' -k2n
"Charlie Fisher's (1989)/"
"Badger Bodger (2001)/"

由于选项--quoting-style=c,这种方法甚至适用于包含换行符或其他难懂字符的文件名。如果您的当然您的文件名不包含换行符,您可以省略此选项。

怎么运行的

sort可以将输入行拆分为字段。该-t选项设置字段分隔符。对于文件,字段分隔符为,而.对于目录,字段分隔符为(。该-k选项确定对哪个字段进行排序。对于上述两种情况,我们要求sort在第二个字段上按数字排序。

答案2

我假设您确定所有文件名都不包含换行符,或者您有某种方法来处理这种可能性。首先,使用以下命令操作文件名sed

命令_to_list_filenames| sed ‘s/.*\.\([0-9][0-9][0-9][0-9]\)\..*/\1.&/’
2001.可以是标题.2001.prop.ext1
1989.另一个潜在的标题.1989.prop.ext2

s命令中的 (substitute) 命令将sed每一行视为下列序列:

  • 任意数量的任意字符 ( .*),
  • 实际期限(\.),
  • 四位数 ([0-9][0-9][0-9][0-9]),
  • 另一个实际时期(\.),以及
  • 另一个字符序列 ( .*)。

请注意,年份 ( [0-9][0-9][0-9][0-9]) 被括在\(和之间\),形成一个组。然后,替换命令将字符串替换为

  • 分组字符,即年份(\1),
  • 句号 ( .),以及
  • 整个输入行(&)。

然后只需按年份(现在出现在行首)对行进行排序并去掉年份即可:

命令_to_list_filenames| sed 's/.*\.\([0-9][0-9][0-9][0-9]\)\..*/\1.&/' | 排序
1989.另一个潜在的标题.1989.prop.ext2
2001.可以是标题.2001.prop.ext1命令_to_list_filenames| sed 's/.*\.\([0-9][0-9][0-9][0-9]\)\..*/\1.&/' | 排序 |
                                                            sed's/^[0-9][0-9][0-9][0-9].//'
另一个潜在的标题.1989.prop.ext2
可能是标题.2001.prop.ext1

可以简单修改该sed命令以处理其他模式。并且sed可以从文件而不是管道获取输入:

% sed 's/.*(\([0-9][0-9][0-9][0-9]\)).*/\1.&/' list_of_directory_names | sort |
                                                            sed 's/^[0-9][0-9][0-9][0-9].//'
Charlie Fisher's (1989)
Badger Bodger (2001)
%

请注意,这适用于包含句点或括号的文本,例如,

Dr. Strangelove.1964.foo
Mrs. Doubtfire.1993.bar

只要它们后面不是四位数字。

.*如果你愿意的话,你可以省略第二步:

命令_to_list_filenames| sed ‘s/.*\.\([0-9][0-9][0-9][0-9]\)\./\1.&/’
2001.可以是标题.2001.prop.ext1
1989.另一个潜在的标题.1989.prop.ext2

相关内容