将 n 个字母的文件名与 ls 匹配

将 n 个字母的文件名与 ls 匹配

我正在 bash 中使用该ls命令,尝试查找长度为 n 的所有文件或目录。假设 n=5

我的命令是:

ls ?????

但这也包括非字母字符,例如句点。例如,以下文件将匹配:

ab.cd    
abd.c

我只想匹配具有 5 个字母或数字名称的文件:

five1
five2    
five3

但不是

abc.d    
ab.cd    
a.bcd

如何修改我的命令?

找到答案:

ls [a-zA-Z0-9][a-zA-Z0-9][a-zA-Z0-9][a-zA-Z0-9][a-zA-Z0-9][a-zA-Z0-9][a-zA-Z0-9]

我找到了答案,但我怎样才能让它不那么难看呢?

答案1

请注意,它并不是ls解释这些通配符。这些 glob 由 shell 扩展为文件名列表,并作为参数传递给ls.不同的 shell 具有不同的通配能力。bash对标准 glob 有一些扩展(借用ksh88并通过 启用),但与或shopt -s extglob等 shell 相比仍然受到限制。zshksh93

zsh

setopt extendedglob
ls -d [[:alnum:]](#c5)

ksh93:

ls -d {5}([[:alnum:]])

或者:

ls -d {5}(\w) # (\w includes underscore in addition to alnums)

或者,如果您想使用扩展正则表达式:

ls -d ~(E)^[[:alnum:]]{5}$

对于bash没有等效通配符的其他 POSIX shell,您需要执行以下操作:

ls -d [[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]]

请注意,[[:alnum:]]包括当前区域设置中的任何字母字符(不仅是拉丁字母,更不用说英语字母了)和0123456789(可能还包括其他类型的数字)。如果您想要英文字母表中的字母,请单独命名字符:

c='[0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]'
unset -v IFS
ls -d $c$c$c$c$c

或者使用 C 语言环境:

(export LC_ALL=C
ls -d [[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]])

答案2

ls -q | grep -Ex '[[:alnum:]]{5}'

答案3

如果您打算ls按照您提到的方式使用,则应该使用该-d选项;否则,它将列出内容任何的目录 其姓名由五个字母和/或数字组成,而不是列出姓名本身。另外,你可以做

ls -d [[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]]

但这与您现在得到的答案完全相同。

另外,如果你不需要ls要在您的命令中使用,您可以使用

echo [[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]]

这将在一行上列出所有匹配项,或者

printf "%s\n" [[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]][:alnum:]]

这会将它们列出在单独的行中。

答案4

在变量中构建表达式:

 e=""; for m in $(seq 1 5); do e="$e[A-Za-z0-9]"; done

将其放入一个函数中以使其美观/可重用:

 alnumglob() {
    local e=""
    for m in $(seq 1 $1) ; do e="$e[A-Za-z0-9]"; done
    echo "$e"
 }

 ls -ld $(alnumglob 5)

相关内容