查找具有最小 4 位数字的文件

查找具有最小 4 位数字的文件

我有很多很多这样的文件[a-zA-Z]+\d\.\d{2}\_\d.\d{4}.end并想要找到 之前具有最小 4 位数字的文件.end。 (如果发生冲突,我想要所有文件)

如何使用 Bash 做到这一点?sort显然,由于字典顺序,单独使用是行不通的。

答案1

使用 GNU 工具,您可以执行以下操作:

find . -regextype posix-extended \
  -regex '.*/[a-zA-Z]+[0-9]\.[0-9]{2}_[0-9]\.[0-9]{4}\.end' -print0 |
  awk -v RS='\0' -F . '
    NR == 1 || $(NF-1) < min {files=$0; min = $(NF-1); next}
    $(NF-1) == min {files = files "\n" $0}
    END {if (NR) print files}'

这是常见模式的示例:我们打印以 NUL 分隔的匹配文件列表(因为 NUL 是唯一不能出现在文件路径中的字符),并处理awk记录分隔符设置为 NUL 的输出(但并非所有awk实现都支持这一点)。

字段分隔符被设定为.NF是字段数,$(NF-1)最后一个字段之前的最后一个也是如此。awk通过与最后一个已知值进行比较来找到最小的数字,并将相应的文件存储在 files awk变量中。

由于我们存储换行符分隔的列表而不是 NUL 分隔的列表,因此它仅用于用户输出。如果您想可靠地对其进行后处理,则需要使用 NUL ("\0"在 awk 中)。

答案2

使用 Bashfind以及sort -t|--field-separator-k|--key选项:

find_files.sh

#!/bin/bash
first_file=$(find . -iname '*.end' | sort -t '.' -k 4.1 | head -1)
IFS='.'
fields=($first_file)
unset IFS
find . -iname "*${fields[3]}.end"

选项-k|--key需要KEYDEF以下形式字段编号字符编号。当-t|--field-separator有效时,字段编号是根据指定的分隔符(在本例中为.)而不是空格来计算的。

然后我们使用 Bash 从第一个文件中提取所需的模式输入字段分隔符,并再次搜索目录以find查找与该模式匹配的文件,以防多个文件共享相同的 4 位数字。

例子:

$ ls -1
abc0.03_1.1921.end
def0.03_9.0311.end
ghi0.03_1.1966.end
jkl1.04_1.1916.end
mno2.04_4.9540.end
pab9.04_1.1994.end
uvx7.04_3.2002.end
yyy1.05_8.0311.end
zzz4.04_1.2097.end
$ ./find_files.sh
./yyy1.05_8.0311.end
./def0.03_9.0311.end

答案3

sort-t-k,这将允许您根据文件名的点分隔部分之一进行排序,在这种情况下应该这样做。

-t, --field-separator=SEP
    use SEP instead of non-blank to blank transition

-k, --key=KEYDEF
    sort via a key; KEYDEF gives location and type

(引自GNU 排序的手册页.)

答案4

perl -le '
   for ( grep { /^[a-zA-Z]+\d\.\d{2}\_\d.\d{4}\.end$/ } <*.end> ) {
      ($n) = /(\d{4})\.end$/;
      $min //= $n;
      $n <= $min and $min = $n, push @{$h{$min}}, $_;
   }
   print for @{$h{$min}};
'

<*>使用通配语法收集所有相关文件,其中,正确的语法文件应由for.

在内部,for我们首先提取最后 4 位数字来确定并将其与正在运行的数字进行比较minimum,如果找到,则将其推送到哈希中。

最后,我们只需打印带有 key 的哈希内容$min

相关内容