我有很多很多这样的文件[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
。