Una versión aún más general que permite usar find
opciones:
#!/bin/bash
set -e
path="$1"
shift 1
while [[ $path != / ]];
do
find "$path" -maxdepth 1 -mindepth 1 "$@"
# Note: if you want to ignore symlinks, use "$(realpath -s "$path"/..)"
path="$(readlink -f "$path"/..)"
done
Por ejemplo (suponiendo que el script se guarda como find_up.sh
)
find_up.sh some_dir -iname "foo*bar" -execdir pwd \;
... imprimirá los nombres de todos some_dir
los antepasados (incluido él mismo) hasta /
que se encuentre un archivo con el patrón.
Cuando utilice readlink -f
el script anterior, seguirá los enlaces simbólicos en el camino, como se señala en los comentarios. En su realpath -s
lugar, puede usar , si desea seguir rutas por nombre ("/ foo / bar" irá a "foo" incluso si "bar" es un enlace simbólico); sin embargo, eso requiere una instalación realpath
que no está instalada de forma predeterminada en La mayoría de las plataformas.
realpath -s
para obtener el comportamiento que desea.readlink
No es parte de la norma. Un script portátil podría implementarse solo con las funciones de shell POSIX.find
oreadlink
. Sugiero cambiarlo a algo así$curpath
para que no sombree la variable de shell.imprimirá el directorio de nivel superior del repositorio actual, si está en uno.
Otras opciones relacionadas:
fuente
Una versión generalizada de la respuesta de Gilles, primer parámetro utilizado para encontrar coincidencia:
Mantiene el uso de enlaces simbólicos.
fuente
Find no puede hacerlo. No puedo pensar en nada más simple que un bucle de shell. (No probado, asume que no hay
/.git
)Para el caso específico de un repositorio de git, puede dejar que git haga el trabajo por usted.
fuente
Si está usando zsh con el globbing extendido habilitado, puede hacerlo con un oneliner:
Explicación (citado de
man zshexpn
):Créditos:
Faux
en#zsh
la sugerencia inicial de uso(../)#.git(:h)
.fuente
(../)
está haciendo ... Ah, ¿y quién / qué esFaux on #zsh
?(../)
por sí solo no significa mucho, pero(../)#
significa tratar de expandir el patrón dentro del paréntesis 0 o más veces, y solo usar los que realmente existen en el sistema de archivos. Debido a que estamos expandiendo de 0 a n directorios principales, buscamos efectivamente hacia arriba a la raíz del sistema de archivos (nota: probablemente desee agregar algo después del patrón para que sea significativo, pero para la ejecución de la iluminaciónprint -l (../)#
). Y#zsh
es un canal IRC,Faux
es un nombre de usuario en él.Faux
sugirió la solución, por lo tanto, el crédito.(../)#.git(/Y1:a:h)
detenerse en el primero encontrado (con una versión reciente de zsh)setopt extended_glob
Esta versión de findup admite la sintaxis "find", como la respuesta de @ sinelaw, pero también admite enlaces simbólicos sin necesidad de realpath. También admite una función opcional "detenerse en", por lo que funciona:
findup .:~ -name foo
... busca foo sin pasar el directorio de inicio.fuente
Descubrí que trabajar con enlaces simbólicos elimina algunas de las otras opciones. Especialmente las respuestas específicas de git. A mitad de camino he creado mi propio favorito de esta respuesta original que es bastante eficiente.
Estoy usando enlaces simbólicos para mis proyectos go porque go quiere el código fuente en una ubicación determinada y me gusta mantener mis proyectos en ~ / projects. Creo el proyecto en $ GOPATH / src y los enlace simbólicamente a ~ / projects. Entonces, la ejecución
git rev-parse --show-toplevel
imprime el directorio $ GOPATH, no el directorio ~ / projects. Esta solución resuelve ese problema.Me doy cuenta de que esta es una situación muy específica, pero creo que la solución es valiosa.
fuente
La solución de Vincent Scheib no funciona para archivos que residen en el directorio raíz.
La siguiente versión sí, y también le permite pasar el directorio inicial como el primer argumento.
fuente
He modificado la solución de sinelaw ser POSIX. No sigue los enlaces simbólicos e incluye la búsqueda en el directorio raíz mediante un bucle do while.
fuente