我想找到单个目录中的所有子目录。我需要按名称长度进行过滤。我想出了以下几点:
find ./directory -maxdepth 1 -type d
如何按名称长度过滤结果——例如,仅过滤超过 4 个字符的子目录?
答案1
您可以使用?
通配符五次:
find ./directory -maxdepth 1 -type d -name '?????*'
这要求匹配项的名称中至少包含五个字符。
答案2
使用zsh
shell,可以按文件类型过滤 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
如果您想忽略隐藏的限定符,请删除限定符。
对于zsh
glob,任何无法解码为字符的字节仍被视为 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 ) 无法解码为字符,并且除了运行之外é
没有其他解决方法,但你会以字节为单位计算长度,而不是人物。find
LC_ALL=C
与此等效的 BSD 版本-regex
是:
find -E . -maxdepth 1 -regex '.*/[^/]{5,}'
或者
find . -maxdepth 1 -regex '.*/[^/]\{5,\}'
(默认是基本正则表达式,而对于 GNU 来说find
,它是一些旧的 emacs 正则表达式方言)。
请记住,多字节字符支持因变体而异。
如果在 GNU 系统上,另一种方法是输出find
NUL 分隔的文件路径(因为 NUL 是文件路径中唯一找不到的字符)并按gawk
名称长度进行过滤:
find . -mindepth 1 -maxdepth 1 -printf '%P\0' |
gawk -v RS='\0' -F/ 'length($NF) > 4'
如果存在无法解码为字符的字节,gawk
则会发出警告,但与 一样,每个字节都会为长度贡献 1 zsh
。