estou usando ols
comando no bash, tentando encontrar todos os arquivos ou diretório de comprimento n. Digamos n = 5
Meu comando é:
ls ?????
Mas isso também incluiria caracteres que não são letras, como ponto final. Por exemplo, os seguintes arquivos corresponderiam:
ab.cd
abd.c
Quero apenas combinar arquivos com nomes de 5 letras ou números:
five1
five2
five3
Mas não
abc.d
ab.cd
a.bcd
Como posso modificar meu comando?
Resposta encontrada:
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]
Encontrei a resposta, mas como posso tornar isso menos feio?
Responder1
Observe que não é ls
isso que interpreta esses globos. Esses globs são expandidos pelo seu shell em uma lista de nomes de arquivos que são passados como argumentos para ls
. Diferentes shells têm diferentes capacidades de globbing. bash
tem algumas extensões sobre globs padrão (emprestados ksh88
e habilitados com shopt -s extglob
), mas ainda é limitado em comparação com shells como zsh
ouksh93
.
Com zsh
:
setopt extendedglob
ls -d [[:alnum:]](#c5)
ksh93
:
ls -d {5}([[:alnum:]])
ou:
ls -d {5}(\w) # (\w includes underscore in addition to alnums)
ou, se você quiser usar expressões regulares estendidas:
ls -d ~(E)^[[:alnum:]]{5}$
Com bash
ou outros shells POSIX que não possuem operadores globbing equivalentes, você precisaria fazer:
ls -d [[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]]
Observe que isso [[:alnum:]]
inclui qualquer caractere alfabético na localidade atual (não apenas alfabetos latinos e muito menos o inglês) e 0123456789
(e possivelmente outros tipos de dígitos). Se você quiser as letras do alfabeto inglês, nomeie os caracteres individualmente:
c='[0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]'
unset -v IFS
ls -d $c$c$c$c$c
Ou use a localidade C:
(export LC_ALL=C
ls -d [[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]])
Responder2
ls -q | grep -Ex '[[:alnum:]]{5}'
Responder3
Se for usar ls
da maneira que você mencionou, você deve usar o-d
opção; caso contrário, ele listará osconteúdode qualquerdiretórios
cujos nomes têm cinco letras e/ou dígitos, em vez de listar os próprios nomes. Além disso, você pode fazer
ls -d [[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]]
mas isso é exatamente o mesmo que a resposta que você tem agora.
Além disso, se você nãoprecisarpara usar ls
em seu comando, você poderia usar
echo [[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]]
que listará todas as correspondências em uma linha, ou
printf "%s\n" [[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]][:alnum:]]
que os listará em linhas separadas.
Responder4
Construa a expressão em uma variável:
e=""; for m in $(seq 1 5); do e="$e[A-Za-z0-9]"; done
Coloque-o em uma função para ser sofisticado/reutilizável:
alnumglob() {
local e=""
for m in $(seq 1 $1) ; do e="$e[A-Za-z0-9]"; done
echo "$e"
}
ls -ld $(alnumglob 5)