He escrito un pequeño script bash para encontrar si un directorio llamado anaconda
o miniconda
en mi usuario $HOME
. Pero no encuentra el miniconda2
directorio en mi casa.
¿Cómo podría solucionar esto?
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
PD: si lo tengo [ -d "$HOME"/miniconda2 ]; then
, entonces encuentra el directorio miniconda2, así que creo que el error radica en la parte"(ana|mini)conda[0-9]?"
Quiero que el guión sea general. Para mí, es miniconda2, pero para algún otro usuario podría ser anaconda2, miniconda3, etc.
command-line
bash
scripts
Jenny
fuente
fuente
Respuestas:
Esto es algo sorprendentemente complicado de hacer bien.
Básicamente,
-d
solo probará un único argumento, incluso si puede hacer coincidir los nombres de archivo con una expresión regular.Una forma sería darle la vuelta al problema y probar directorios para una coincidencia de expresiones regulares en lugar de probar la coincidencia de expresiones regulares para directorios. En otras palabras, recorra todos los directorios
$HOME
con un simple glob de shell y pruebe cada uno contra su expresión regular, rompiendo una coincidencia y finalmente probando si laBASH_REMATCH
matriz no está vacía:Una forma alternativa sería utilizar un globo de caparazón extendido en lugar de la expresión regular y capturar cualquier coincidencia de globo en una matriz. Luego pruebe si la matriz no está vacía:
El seguimiento
/
garantiza que solo los directorios coincidan; lanullglob
evita que la cáscara de regresar la cadena sin igual en el caso de los partidos cero.Para hacer que sea recursivo, configure la
globstar
opción de shell (shopt -s globstar
) y luego respectivamente: -(versión regex):
for d in "$HOME"/**/; do
(versión glob extendida):
dirs=( "$HOME"/**/@(ana|mini)conda?([0-9])/ )
fuente
?([0-9])
en lugar de@(|[0-9])
:?(...)
coincide con cero o uno, igual que el?
cuantificador de expresiones regulares .~/{ana,mini}conda{0..9}*/
mini
oanaconda
se instala en$HOME/sub-directories
? Por ejemplo$HOME/sub-dir1/sub-dir2/miniconda2
globstar
De hecho, como ya se mencionó, esto es complicado. Mi enfoque es el siguiente:
find
y sus capacidades de expresiones regulares para encontrar los directorios en cuestión.find
imprimir unx
para cada directorio encontradox
es en una cadenaAsí:
Explicación:
find $HOME -maxdepth 1
encuentra todo a continuación,$HOME
pero restringe la búsqueda a un nivel (es decir, no se repite en subdirectorios).-type d
restringe la búsqueda a solod
irectorios-regextype egrep
dice confind
qué tipo de expresión regular tratamos. Esto es necesario porque cosas como[0-9]?
y(…|…)
son algo especiales yfind
no las reconoce por defecto.-regex "$HOME/(ana|mini)conda[0-9]?"
es la expresión regular real que queremos buscar-printf 'x'
solo imprime unx
por cada cosa que satisfaga las condiciones anteriores.fuente
-bash: -regex: command not found found one of the directories
printf
Por ejemplo, cuando ejecuto el script, funciona bien, pero no encuentra el comando printf cuando no hay coincidencia, pero creo que es porque no hay nada que imprimir.-bash: -printf: command not found no match.
-printf
no es un comando sino un argumento parafind
. Eso es lo que hace la barra invertida al final de la línea anterior.-quit
después de imprimir la ruta encontrada, a menos que quiera seguir detectando ambigüedad.x
en su lugar:foundDir=$(find $HOME -maxdepth 1 -type d -regextype egrep -regex "$HOME/(ana|mini)conda[0-9]?" -print -quit); echo "found $foundDir"
Puede recorrer una lista de nombres de directorio que desea probar y actuar si existe uno de ellos:
Obviamente, esta solución no permite la potencia de expresión regular completa, pero la expansión del refuerzo de caparazón y la abrazadera es igual al menos en el caso que usted mostró. El bucle sale tan pronto como existe un directorio y desarma la variable establecida previamente
a
. En laecho
línea siguiente , la expansión del parámetro se${a+not }
expande a nada sia
se establece (= no se encuentra el directorio) y "no" más.fuente
Posible solución es buscar miniconda y anaconda por separado como se muestra a continuación
Pero si alguien tiene sugerencias, me gustaría saber por qué no podemos pasar una expresión regular cuando buscamos directorios.
fuente
shopt -s nullglob; dirs=( "$HOME"/miniconda* "$HOME"/anaconda* ); if (( ${#dirs[@]} > 0 )); then ...
] || [
con el-o
que al menos no debería romperse si se encuentran ambos directorios ya que ambos globos de directorio se buscan en la misma prueba.