我正在 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 相比仍然受到限制。zsh
ksh93
和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)