按长度过滤查找结果

按长度过滤查找结果

我想找到单个目录中的所有子目录。我需要按名称长度进行过滤。我想出了以下几点:

find ./directory -maxdepth 1 -type d

如何按名称长度过滤结果——例如,仅过滤超过 4 个字符的子目录?

答案1

您可以使用?通配符五次:

find ./directory -maxdepth 1 -type d -name '?????*'

这要求匹配项的名称中至少包含五个字符。

答案2

使用zshshell,可以按文件类型过滤 glob(此处目录) 使用全局限定符,并且extendedglob打开该选项后,您将获得(#cX,Y)类似于 ERE 的全局运算符{X,Y},因此您可以执行以下操作:

set -o extendedglob
print -rC1 -- ?(#c5,)(ND/)

列出print r类型1 C的文件目录( glob 限定符)由一个或多个字符 ( )/组成。5?

?(#c5,12)将为 5 到 12 个字符,?(#c,5)?(#c0,5)0 到 5 个字符(并不是说您可以获得包含 0 个字符的文件名)。

D如果您想忽略隐藏的限定符,请删除限定符。

对于zshglob,任何无法解码为字符的字节仍被视为 1(并且将通过 进行匹配?)。

对于包括 GNU 在内的某些find实现find,至少在 GNu 系统上(使用 GNU 正则表达式/fnmatch()来自 GNU libc),它们既不匹配也不匹配?( *也不匹配 regex .),因此:

find . -maxdepth -name '?????*' -type d

或者

find . -maxdepth 1 -regextype posix-extended -regex '.*/[^/]{5,}' -type d

$'St\xe9phane'例如,如果在 UTF-8 语言环境中运行,则无法匹配目录,因为 0xe9 字节 (ISO8859-1 ) 无法解码为字符,并且除了运行之外é没有其他解决方法,但你会以字节为单位计算长度,而不是人物。findLC_ALL=C

与此等效的 BSD 版本-regex是:

find -E . -maxdepth 1 -regex '.*/[^/]{5,}'

或者

find . -maxdepth 1 -regex '.*/[^/]\{5,\}'

(默认是基本正则表达式,而对于 GNU 来说find,它是一些旧的 emacs 正则表达式方言)。

请记住,多字节字符支持因变体而异。

如果在 GNU 系统上,另一种方法是输出findNUL 分隔的文件路径(因为 NUL 是文件路径中唯一找不到的字符)并按gawk名称长度进行过滤:

find . -mindepth 1 -maxdepth 1 -printf '%P\0' |
  gawk -v RS='\0' -F/ 'length($NF) > 4'

如果存在无法解码为字符的字节,gawk则会发出警告,但与 一样,每个字节都会为长度贡献 1 zsh

相关内容