我正在 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)