如何根据文件名范围查找文件?

如何根据文件名范围查找文件?

我有一些带有数字名称的文件:2341a.po4567211someword.po0012.po等。我想根据数字范围查找一组文件。例如[126 - 363]

通常我使用正则表达式find。任何数值范围都可以由两个正则表达式和[N, M]组成。larger than Nless than M

大于N的:

如果,那么我首先为所有人N = vxyz进行匹配value > V000, (V=v+1)[V-9]\d{3,}

然后将vX00, X=x+1, 与v[X-9]\d\d

然后将vxY0, Y=y+1, 与vx[Y-9]\d

最后vxy[z-9]

例子:

为了匹配number>=234,我使用:

`^(0*([3-9]\d{2,}|2[4-9]\d|23[4-9]))`

小于M的:

基于类似的逻辑,我们将有:

^(0*(vxy[0-z]|vx[0-Y]\d|v[0-X]\d\d|[1-V]\d\d|\d{1,3}))[^0-9]

Y=y-1,X=x-1,V=v-1

例如,以下命令将查找 [253, 326] 之间的任何文件:

find . -maxdepth 1 -type f -regextype posix-extended -iregex '^\./0*([3-9][0-9]{2,}|2[6-9][0-9]{2,}|25[3-9]).*' -iregex '^\./0*(32[0-6]|3[0-1][0-9]|[0-2][0-9][0-9]|[0-9]{1,2})[^0-9].*'

然而,这种方法对于处理长数字来说太烦人了。有没有更好、更简单的方法来做到这一点?

答案1

zsh

setopt extendedglob # best in ~/.zshrc
ls -ld -- <126-253>(*.po~[0-9]*)

也就是说,十进制数字 126 到 253(也接受 000126),后跟以十进制数字结尾.po且不以十进制数字开头的内容)。

递归地,包括隐藏目录和仅常规文件:

ls -ld -- **/<126-253>(*.po~[0-9]*)(D.)

如果zargs您遇到arg list too long错误。

要使用变量而不是文字数字,您不能这样做<$low-$high>。该<x-y>运算符与重定向运算符重叠(echo <3-4> z在 POSIX shell 中,echo使用从3-文件重定向的输入和 fd 4 进入z)运行,zsh尝试通过仅接受文字数字来最小化冲突风险。但是,您可以将该运算符用作globsubsting 扩展的一部分,例如:

low=126 high=253
ls -ld -- ${~:-"<$low-$high>"}(*.po~[0-9]*)

其中${~expansion}启用globsubst(允许扩展进行通配)是expansion${:-"text"}一种特殊形式,${var:-default}可以将扩展扩展到任意text

答案2

您可以生成一个包含要查找的数字的文件列表,并将它们放在参数列表中以供find使用xargs。例如,使用,与问题中bash使用 as 等效的是:-maxdepth 1

echo {253..326} | xargs sh -c 'find "$@" -type f -maxdepth 0' sh

请注意,您可以使用-I选项xargs(ie xargs -I{} find {} -type f),但 GNUxargs强制-L 1使用此选项,这意味着为每个参数启动单独的查找过程。使用sh可以解决这个问题。

对于任意深度,您可以执行以下操作:

printf -- '-o -name %d ' {254..326} |
  xargs -n 3000 sh -c 'find -type f \( -name 253 "$@" \)' sh

应选择参数-n(每个命令添加的最大参数数量),以便限制参数列表结构的大小xargs。如果太大,则可能会由于参数列表的总体大小而不是参数数量而达到限制。它应该是 3 的倍数,这样列表中就不会留下尾随-o或。-name

答案3

对格雷姆答案的强力扩展:

find . -type f -regextype posix-awk -regex ".*/0*($(seq -s'|' 254 456)).*" 

如果您需要 POSIX ,您可以使用\|代替|\(\)代替()(但是,这seq不是 POSIX,不是吗?)。

$ find . -maxdepth 2 -type f -regextype posix-awk -regex ".*/0*($(seq -s'|' 254 456)).*"    
./.fontconfig/3047814df9a2f067bd2d96a2b9c36e5a-le32d4.cache-3
./.fontconfig/3830d5c3ddfd5cd38a049b759396e72e-le32d4.cache-3
./.fontconfig/385c0604a188198f04d133e54aba7fe7-le32d4.cache-3
./Documents/374620-63301.pdf
./4567211someword.po

唔。看起来我们应该添加一个非数字字符来标记数字的结尾。也许".*/0*($(seq -s'|' 254 456))[^0-9].*"

答案4

find | perl -ne 'print if(m!^\./(\d+)! and $1 > 126 and $1 <363)'

...可能会添加其他答案中提出的一些好主意。

正则表达式可能需要一些调整(例如^\./(\d+)\w*.po$:)

相关内容