匹配不连续的数字文件名

匹配不连续的数字文件名

我正在尝试执行命令来匹配目录中的某个文件子集。所有文件都有一个名称时间戳.jpg,每个文件之间大约(但不完全)30 分钟。

基于这个问题和答案,我想出了这个命令(用于echo测试):

for x in *([1510852838790,1510898258530]).jpg; do echo $x; done

但是,这会输出以下内容(注意标有 **** 的输入数字):

1510770572978.jpg
1510770810272.jpg
1510772133873.jpg
1510772378293.jpg
1510772979803.jpg
1510773223237.jpg
1510852838790.jpg****
1510852959075.jpg
1510853079321.jpg
1510853808012.jpg
1510855019583.jpg
1510855380099.jpg
1510855983715.jpg
1510857313787.jpg
1510858282007.jpg
1510858889310.jpg
1510859009339.jpg
1510859253091.jpg
1510870852822.jpg
1510871097118.jpg
1510871335799.jpg
1510871703808.jpg
1510871823158.jpg
1510872311110.jpg
1510872553750.jpg
1510872917378.jpg
1510873159981.jpg
1510875721755.jpg
1510877181978.jpg
1510877301888.jpg
1510878157813.jpg
1510878278033.jpg
1510878522553.jpg
1510879250080.jpg
1510879738575.jpg
1510879859397.jpg
1510880105392.jpg
1510880717151.jpg
1510880957839.jpg
1510881325005.jpg
1510881570373.jpg
1510881811325.jpg
1510882295590.jpg
1510882785823.jpg
1510883275381.jpg
1510885101702.jpg
1510885222385.jpg
1510885711900.jpg
1510887172253.jpg
1510887292977.jpg
1510887538312.jpg
1510888029878.jpg
1510889975298.jpg
1510890221372.jpg
1510890709993.jpg
1510890830832.jpg
1510890951888.jpg
1510891193150.jpg
1510891313575.jpg
1510891922503.jpg
1510892537090.jpg
1510892900397.jpg
1510893021713.jpg
1510893385557.jpg
1510893992777.jpg
1510895212923.jpg
1510895333595.jpg
1510895819713.jpg
1510897039331.jpg
1510897159572.jpg
1510898133110.jpg
1510898258530.jpg****
1510900807071.jpg
1510900927933.jpg
1510902272277.jpg
1510902393272.jpg
1510902998172.jpg
1510903851131.jpg
1510905309558.jpg
1510905557228.jpg
1510907015107.jpg
1510907751301.jpg
1510907877003.jpg
1510907992905.jpg
1510908113731.jpg
1510908598199.jpg
1510908719029.jpg
1510909570015.jpg
1510909811208.jpg
1510909931529.jpg
1510910181722.jpg
1510911388852.jpg
1510911513951.jpg
1510911879905.jpg
1510912727850.jpg
1510913088390.jpg
1510913818319.jpg
1510915397801.jpg
1510917103919.jpg
1510917711228.jpg
1510917832327.jpg
1510917953273.jpg
1510918319775.jpg
1510918803832.jpg
1510918929550.jpg
1510919172181.jpg
1510919293195.jpg
1510919898053.jpg
1510922089190.jpg
1510922579951.jpg
1510923308092.jpg
1510923550590.jpg
1510923793010.jpg
1510925011829.jpg
1510925137958.jpg
1510925987153.jpg
1510927083913.jpg
1510927812212.jpg
1510928298155.jpg
1510928910223.jpg
1510929031559.jpg
1510930370780.jpg
1510930733981.jpg
1510930981902.jpg
1510932080591.jpg
1510932809212.jpg
1510933290952.jpg
1510933903131.jpg
1510935121827.jpg
1510935237921.jpg
1510935725717.jpg
1510937189535.jpg
1510937919235.jpg
1510938283032.jpg
1510938895279.jpg
1510939137978.jpg
1510939501755.jpg
1510939992901.jpg

输出列表包含目录中 798 个文件中的 138 个文件名,但它在第一个输入编号之前和第二个输入编号之后包含其他文件。这是为什么?我该如何纠正?

答案1

[1510852838790,1510898258530]是一个标准的全局运算符,它匹配字符集中的一个字符。[ab,c]匹配ab或。,c所以与或[1510852838790,1510898258530]相同。也就是说,它匹配除 和 之外的逗号或十进制数字。[,01235789][,0-357-9]46

*(...)是匹配 0 个或多个 的Korn shell glob 运算符(也受zsh -o kshgloband支持) 。bash -O extglob...

So匹配后跟 的*([1510852838790,1510898258530]).jpg任何字符序列。,01235789.jpg

如果要匹配由 1510852838790 到 1510898258530 之间的十进制数字组成的任何字符串,则需要shell<x-y>的 glob 运算符zsh

printf '%s\n' <1510852838790-1510898258530>.jpg

您链接到的答案是指zshshell 的另一个功能(同样不是bash):[x,y]glob 限定符。

Glob 限定符是(...)添加到 glob 末尾的一部分,用于添加除基于名称的条件之外的一些条件。

例如,*.jpg(.)*.jpg仅限于常规文件(不包括目录、符号链接、套接字、fifo...)

*.jpg([5,10])是匹配文件列表中的第 5 个到第 10 个文件*.jpg(按词法排序)。

请注意,zsh glob 限定符确实与kshglob.如果您想使用(但通常您不会,除非您想解释用于 ksh 的代码,因为 zsh 扩展的 glob 通常比 ksh 的更好),您通常kshglob还想禁用该bareglobqual选项(或使用 ksh 模拟模式)emulate ksh照顾好这一点并启用更多类似 ksh 的行为)。

扩展 glob中kshs的等价物是(类似于正则表达式,只不过 in glob用于其他用途)。*(x)zshx#x**

bash没有<x-y>glob 运算符,也没有 glob 限定符。在 中bash,您可以执行以下操作:

zsh -c "printf '%s\n' <1510852838790-1510898258530>.jpg"

或者您可以打印所有number.jpg文件并使用以下命令对输出进行后处理awk

shopt -s extglob
printf '%s\n' *([0-9]).jpg |
  awk -F. '$1 >= 1510852838790 && $1 <= 1510898258530'

不管怎样,如果你想尝试找到数字序列中的间隙,你可能awk无论如何都会想使用。

就像(回到使用zsh):

print -l <->.jpg(n) | awk -F. '
  {diff = ($0 - prev) / 1000 / 60}
  NR > 1 && (diff < 29 || diff > 31) {print $0, "diff=" diff}
  {prev = $0}'

答案2

如果您的文件名都是时间戳,您可以在算术上下文中比较它们(( ))。这将获取所有以数字命名的jpg文件,去除扩展名,并将它们与上限和下限进行比较:

#!/bin/bash

shopt -s extglob

for f in *([0-9]).jpg; do
   timestamp="${f%%.*}"
   (( "$timestamp" >= 1510852838790 && "$timestamp" <= 1510898258530 )) && echo "$f"
done

exit

相关内容