Uma versão ainda mais geral que permite o uso de find
opções:
#!/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 exemplo (supondo que o script seja salvo como find_up.sh
)
find_up.sh some_dir -iname "foo*bar" -execdir pwd \;
... imprimirá os nomes de todos some_dir
os ancestrais (incluindo ele próprio) até os /
quais um arquivo com o padrão seja encontrado.
Ao usar readlink -f
o script acima, siga os links simbólicos no caminho, conforme observado nos comentários. Em realpath -s
vez disso, você pode usar se desejar seguir os caminhos pelo nome ("/ foo / bar" aumentará para "foo" mesmo que "bar" seja um link simbólico) - no entanto, isso requer instalação realpath
que não é instalada por padrão em maioria das plataformas.
realpath -s
para obter o comportamento que deseja.readlink
não faz parte do padrão. Um script portátil pode ser implementado apenas com recursos de shell POSIX.find
oureadlink
. Sugiro alterá-lo para algo como$curpath
isso, para que não oculte a variável shell.imprimirá o diretório de nível superior do repositório atual, se você estiver em um.
Outras opções relacionadas:
fonte
Uma versão generalizada da resposta de Gilles, primeiro parâmetro usado para encontrar correspondência:
Mantém o uso de links simbólicos.
fonte
Encontrar não pode fazer isso. Não consigo pensar em nada mais simples do que um loop de shell. (Não testado, assume que não há
/.git
)Para o caso específico de um repositório git, você pode deixar o git fazer o trabalho por você.
fonte
Se você estiver usando o zsh com o globbing estendido ativado, poderá fazê-lo com um oneliner:
Explicação (citada em
man zshexpn
):Créditos:
Faux
on#zsh
para a sugestão inicial de usar(../)#.git(:h)
.fonte
(../)
está fazendo ... Ah, e quem / o que éFaux on #zsh
?(../)
si só não significa muito, mas(../)#
significa tentar expandir o padrão entre parênteses 0 ou mais vezes e usar apenas os que realmente existem no sistema de arquivos. Como estamos expandindo de 0 para n diretórios pai, pesquisamos efetivamente para cima até a raiz do sistema de arquivos (nota: você provavelmente deseja adicionar algo após o padrão para torná-lo significativo, mas para a execução da iluminaçãoprint -l (../)#
). E#zsh
é um canal de IRC,Faux
é um nome de usuário nele.Faux
sugeriu a solução, portanto o crédito.(../)#.git(/Y1:a:h)
parar no primeiro encontrado (com uma versão recente do zsh)setopt extended_glob
Esta versão do findup suporta a sintaxe "find", como a resposta do @ sinelaw, mas também suporta links simbólicos sem precisar de caminho real. Ele também suporta um recurso "parar em" opcional, portanto, isso funciona:
findup .:~ -name foo
... procura por foo sem passar o diretório inicial.fonte
Descobri que trabalhar com links simbólicos mata algumas das outras opções. Especialmente as respostas específicas do git. Na metade, criei meu próprio favorito a partir dessa resposta original, que é bastante eficaz.
Estou usando links simbólicos para meus projetos go porque go quer código fonte em um determinado local e eu gosto de manter meus projetos em ~ / projects. Crio o projeto em $ GOPATH / src e os vinculo a ~ / projects. Portanto, a execução
git rev-parse --show-toplevel
imprime o diretório $ GOPATH, não o diretório ~ / projects. Esta solução resolve esse problema.Sei que é uma situação muito específica, mas acho que a solução é valiosa.
fonte
A solução de Vincent Scheib não funciona para arquivos que residem no diretório raiz.
A versão a seguir faz e também permite passar o diretório inicial como o 1º argumento.
fonte
Eu modifiquei a solução do sinelaw para ser POSIX. Ele não segue links simbólicos e inclui a pesquisa no diretório raiz usando um loop do while.
fonte