Quiero usar find
para buscar archivos en un conjunto de carpetas restringido por comodines, pero donde hay espacios en el nombre de la ruta.
Desde la línea de comandos, esto es fácil. Los siguientes ejemplos funcionan todos.
find te*/my\ files/more -print
find te*/'my files'/more -print
find te*/my' 'files/more -print
Estos encontrarán archivos en, por ejemplo, terminal/my files/more
y tepid/my files/more
.
Sin embargo, necesito que esto sea parte de un script; lo que necesito es algo como esto:
SEARCH='te*/my\ files/more'
find ${SEARCH} -print
Desafortunadamente, haga lo que haga, parece que no puedo mezclar comodines y espacios en un find
comando dentro de un script. El ejemplo anterior devuelve los siguientes errores (observe la duplicación inesperada de la barra invertida):
find: ‘te*/my\\’: No such file or directory
find: ‘files/more’: No such file or directory
Intentar usar comillas también falla.
SEARCH="te*/'my files'/more"
find ${SEARCH} -print
Esto devuelve los siguientes errores, habiendo ignorado el significado de las citas:
find: ‘te*/'my’: No such file or directory
find: ‘files'/more’: No such file or directory
Aquí hay un ejemplo más.
SEARCH='te*/my files/more'
find ${SEARCH} -print
Como se esperaba:
find: ‘te*/my’: No such file or directory
find: ‘files/more’: No such file or directory
Cada variación que he intentado devuelve un error.
Tengo una solución alternativa, que es potencialmente peligrosa porque devuelve demasiadas carpetas. Convierto todos los espacios en un signo de interrogación (comodín de un solo carácter) como este:
SEARCH='te*/my files/more'
SEARCH=${SEARCH// /?} # Convert every space to a question mark.
find ${SEARCH} -print
Este es el equivalente de:
find te*/my?files/more -print
Esto devuelve no solo las carpetas correctas, sino también terse/myxfiles/more
, lo que no se supone que debe hacer.
¿Cómo puedo lograr lo que intento hacer? Google no me ha ayudado :(
SEARCH: command not found
lafind -print
ejecución del comando .find "${SEARCH}" -print
?te*/'my files'/more
.Respuestas:
El mismo comando exactamente debería funcionar bien en un script:
Si necesita tenerlo como variable, se vuelve un poco más complejo:
ADVERTENCIA:
Usarlo de
eval
esa manera no es seguro y puede resultar en la ejecución de código arbitrario y posiblemente dañino si los nombres de sus archivos pueden contener ciertos caracteres. Consulte las preguntas frecuentes 48 de bash para obtener más información.Es mejor pasar el camino como argumento:
Otro enfoque es evitar por
find
completo y utilizar las funciones de globing y globs extendidos de bash:La
globstar
opción bash te permite usar**
para hacer coincidir recursivamente:Para que funcione al 100% como buscar e incluir archivos de puntos (archivos ocultos), use
Puedes incluso
echo
igualarlos directamente sin el bucle:fuente
¿Qué hay de las matrices?
(*)
se expande en una matriz de lo que coincida con el comodín. Y se"${SEARCH[@]}"
expande en todos los elementos de la matriz ([@]
), con cada uno citado individualmente.Tardíamente, me doy cuenta de que debe ser capaz de hacer esto. Algo como:
fuente
INPUTPATH='te*/my files/more
ySEARCH=(${INPUTPATH})
. No importa cómo varíe la forma en que hago esto, todavía termino con un resultado no funcional. Esto parece imposible!find
el-path
filtro? Utiliza comodines y definitivamente no necesita expansión.-path
. En los últimos 10 minutos, sin embargo, he descubierto la respuesta:eval
¡ uso ! Parece ser más simple que-path
.Finalmente he encontrado la respuesta.
Agregue una barra diagonal inversa a todos los espacios:
En este punto,
SEARCH
contienete*/my\ files/more
.Entonces, use
eval
.¡Es así de simple! El uso
eval
evita la interpretación que${SEARCH}
proviene de una variable.fuente