保留最新的两个版本,删除剩余的

aha*_*123 1 bash ksh filenames rm

我在一个目录中有一个文件列表(比如下面的 xsl 格式)。我想保留所有文件的最后两个版本。(我可以删除剩余的文件)

{A}_1.0.xsl
{A}_2.0.xsl
{A}_3.0.xsl
{A}_4.1.xsl
{A}_5.0.xsl
{A}_6.0.xsl
{B}_1.0.xsl
{B}_2.0.xsl
{B}_3.0.xsl
{B}_4.0.xsl
{C}_1.0.xsl
{C}_2.0.xsl
{C}_3.0.xsl
Run Code Online (Sandbox Code Playgroud)

目录中存在的剩余文件应该是

{A}_5.0.xsl
{A}_6.0.xsl
{B}_3.0.xsl
{B}_4.0.xsl
{C}_2.0.xsl
{C}_3.0.xsl
Run Code Online (Sandbox Code Playgroud)

如何实现?

Sté*_*las 5

假设当前目录中的所有文件名都遵循该模式,使用GNUls:

ls -rv | awk -F_ '++n[$1]>2' | xargs rm
Run Code Online (Sandbox Code Playgroud)

| xargs rm如果您想检查它将首先删除的内容,您可以省略。

假设 in 部分{...}不包含空格、换行符、单引号、双引号、反斜杠、制表符或下划线字符。

关键是-vGNU 实现的ls按版本号排序的选项。如果您没有 GNU ls,但有zsh,zsh您可以使用:

print -rl -- *(nOn)
Run Code Online (Sandbox Code Playgroud)

达到同样的效果。

现在,如果当前目录可以包含任何内容,并且您只想处理形式为{x}_y.z.xslwherex可以是任何内容y并且z是正十进制整数的文件,则必须编写它(zsh语法):

printf '%s\0' \{*\}_<->.<->.xsl(.nOn) | perl -0 -lne '
  unlink if /\{.*\}/s && ++$n{$&} > 2'
Run Code Online (Sandbox Code Playgroud)

或者使用GNUls 而GNU bash不是zsh:

eval "files=($(ls -rv --quoting-style=shell-always))"
printf '%s\0' "${files[@]}" | perl -0 -lne '
  unlink if /^\{(.*)\}_\d+\.\d+\.xsl\z/s && ++$n{$1} > 2'
Run Code Online (Sandbox Code Playgroud)