Eu escrevi um pequeno script bash para descobrir se um diretório nomeado anaconda
ou miniconda
no meu usuário $HOME
. Mas ele não encontra o miniconda2
diretório em minha casa.
Como eu poderia consertar isso?
if [ -d "$HOME"/"(ana|mini)conda[0-9]?" ]; then
echo "miniconda directory is found in your $HOME"
else
echo "anaconda/miniconda is not found in your $HOME"
fi
PS: Se eu tiver [ -d "$HOME"/miniconda2 ]; then
, ele encontra o diretório miniconda2, então acho que o erro está na parte"(ana|mini)conda[0-9]?"
Eu quero que o script seja geral. Para mim, é miniconda2, mas para outros usuários, pode ser anaconda2, miniconda3 e assim por diante.
command-line
bash
scripts
Jenny
fonte
fonte
Respostas:
É uma coisa surpreendentemente complicada de se fazer bem.
Fundamentalmente,
-d
testará apenas um único argumento - mesmo se você puder corresponder os nomes de arquivos usando uma expressão regular.Uma maneira seria inverter o problema e testar os diretórios para uma correspondência de regex em vez de testar a correspondência de regex para diretórios. Em outras palavras, faça um loop sobre todos os diretórios
$HOME
usando um simples shell glob e teste cada um deles em relação ao seu regex, quebrando uma correspondência e finalmente testando se aBASH_REMATCH
matriz não está vazia:Uma maneira alternativa seria usar um globo de shell estendido no lugar do regex e capturar quaisquer correspondências de globos em uma matriz. Em seguida, teste se a matriz não está vazia:
O final
/
garante que apenas os diretórios sejam correspondidos; onullglob
evita que o shell de retornar a string inigualável no caso de zero partidas.Para tornar recursivo, defina a
globstar
opção shell (shopt -s globstar
) e, em seguida, respectivamente: -(versão regex):
for d in "$HOME"/**/; do
(versão estendida glob):
dirs=( "$HOME"/**/@(ana|mini)conda?([0-9])/ )
fonte
?([0-9])
no lugar de@(|[0-9])
-?(...)
corresponde a zero ou um, igual ao?
quantificador de expressão regular.~/{ana,mini}conda{0..9}*/
mini
ouanaconda
está instalado em$HOME/sub-directories
? Por exemplo$HOME/sub-dir1/sub-dir2/miniconda2
globstar
De fato, como já mencionado, isso é complicado. Minha abordagem é a seguinte:
find
e seus recursos regex para encontrar os diretórios em questão.find
imprimir umx
para cada diretório encontradox
es em uma stringPortanto:
Explicação:
find $HOME -maxdepth 1
localiza tudo abaixo,$HOME
mas restringe a pesquisa a um nível (ou seja: não recursa em subdiretórios).-type d
restringe a pesquisa apenas ad
irectorias-regextype egrep
dizfind
que tipo de expressão regular lidamos. Isso é necessário porque coisas como[0-9]?
e(…|…)
são um pouco especiais efind
não as reconhecem por padrão.-regex "$HOME/(ana|mini)conda[0-9]?"
é a expressão regular real que queremos procurar-printf 'x'
apenas imprime umx
para cada coisa que satisfaça as condições anteriores.fonte
-bash: -regex: command not found found one of the directories
printf
Por exemplo, quando executo o script, ele funciona ok, mas não encontra o comando printf quando não há correspondência, mas acho que é porque não há nada para imprimir ?.-bash: -printf: command not found no match.
-printf
não é um comando, mas um argumento parafind
. É o que a barra invertida no final da linha anterior faz.-quit
depois de imprimir o caminho encontrado, a menos que você queira continuar detectando ambiguidade.x
:foundDir=$(find $HOME -maxdepth 1 -type d -regextype egrep -regex "$HOME/(ana|mini)conda[0-9]?" -print -quit); echo "found $foundDir"
Você pode fazer um loop sobre uma lista de nomes de diretórios que deseja testar e agir sobre ela, se existir um deles:
Obviamente, essa solução não permite a potência máxima de regex, mas a expansão de globbing e brace do shell é igual pelo menos no caso que você mostrou. O loop sai assim que um diretório existe e desativa a variável definida anteriormente
a
. Naecho
linha subseqüente , a expansão do parâmetro se${a+not }
expande para nada sea
estiver definida (= nenhum diretório encontrado) e "not" em outros casos.fonte
Possível solução alternativa é pesquisar miniconda e anaconda separadamente, como mostrado abaixo
Mas se alguém tiver sugestões, eu gostaria de saber por que não podemos passar um regex ao procurar por diretórios.
fonte
shopt -s nullglob; dirs=( "$HOME"/miniconda* "$HOME"/anaconda* ); if (( ${#dirs[@]} > 0 )); then ...
] || [
--o
lo, pelo menos não deve quebrar se os dois diretórios forem encontrados, pois os dois globs de diretório são procurados no mesmo teste.