Bash CD até em determinada pasta

16

Faço muito trabalho no Magento, assim como muitas pessoas com quem trabalho, e é irritante ter que digitar:

cd ../../../../../../

Para descobrir apenas alguns diretórios da pasta raiz 'httpdocs', estou tentando criar um script que siga este pseudocódigo:

while lowest level directory != httpdocs
    cd ../
end while;

Parece bem simples, estou assumindo que precisaria fazer alguma forma de grep para verificar se a última parte do diretório de trabalho atual é httpdocs, se não continuar subindo de nível até que seja verdade.

Eu estive procurando aprender o bash para isso, embora pareça que já exista algo semelhante por aí, e a sintaxe me deixa sem fim.

user652650
fonte

Respostas:

8

Isso deve ser uma função do shell , não um script, porque um script é executado em um novo shell (e, portanto, não pode alterar o diretório do shell original).

function cdroot()
{
  while [[ $PWD != '/' && ${PWD##*/} != 'httpdocs' ]]; do cd ..; done
}

É claro que você pode nomear a função como quiser.

Alguma explicação: O primeiro teste ( $PWD != '/') é à prova de falhas, caso você não cdrootesteja dentro de uma pasta httpdocs. Parará quando você chegar à raiz.

O segundo teste ( ${PWD##*/} != 'httpdocs') é um pouco mais complicado. $PWDé uma variável que contém o caminho do diretório atual. ${PWD##*/}apara tudo, inclusive a última barra.

cjm
fonte
A desvantagem deste iterativo é que você perde a capacidade de fazer apenas um processo cd -posterior para voltar para onde estava.
Ezequiel Muns
27

Eu tenho uma função chamada uptono meu .bashrc que permite que você vá para qualquer diretório no caminho atual pelo nome:

upto ()
{
    if [ -z "$1" ]; then
        return
    fi
    local upto=$1
    cd "${PWD/\/$upto\/*//$upto}"
}

Eu também tenho conclusão para esta função, para que ela me dê nomes de diretório válidos e conclusão ao clicar na guia:

_upto()
{
    local cur=${COMP_WORDS[COMP_CWORD]}
    local d=${PWD//\//\ }
    COMPREPLY=( $( compgen -W "$d" -- "$cur" ) )
}
complete -F _upto upto

Além disso, tenho outra função jdque me permite pular para qualquer diretório abaixo do atual:

jd(){
    if [ -z "$1" ]; then
        echo "Usage: jd [directory]";
        return 1
    else
        cd **"/$1"
    fi
}

Exemplo:

[/www/public_html/animals/hippopotamus/habitat/swamps/images] $ upto h[TAB][TAB]
habitat       hippopotamus
[/www/public_html/animals/hippopotamus/habitat/swamps/images] $ upto hippopotamus
[/www/public_html/animals/hippopotamus] $ jd images
[/www/public_html/animals/hippopotamus/habitat/swamps/images] $ 
dogbane
fonte
Você também pode adicionar um alias para upto httpdocs.
CJM
@drogbane: jdnão parece funcionar em todos os casos, você se importaria de explicar como funciona?
Cesar
@ Cesar usa globstar ( **). Para habilitar esse recurso no seu shell bash, use shopt -s globstar.
dogbane
2
Isso é feito de maneira tão brilhante que eu gostaria de poder votar duas vezes.
droope
1
Incluí uma detecção e ativação dinâmicas de shopt na jdfunção, consulte gist.github.com/Rob--W/5888648 . Eu só testei com o Bash 4.2.45, então YMMV.
Rob W
5

A função bash mais simples que você pode colocar na sua .bashrcque eu possa pensar (simples porque ela não usa loops ou processos externos) é:

cdup() {
    cd "${PWD/\/httpdocs\/*//httpdocs}"
}

Este usa a substituição Padrão expansão de parâmetros para substituir tudo depois /httpdocs/em $PWDcom `/ httpdocs'. Parece muito confuso porque temos que escapar das barras no caminho para diferenciá-las das barras na sintaxe de expansão do bash. Além disso, não escape barras invertidas na cadeia de substituição, por isso também parecerá inconsistente.

Se não houver /httpdocs/no caminho atual, nenhuma substituição será executada e ela será alterada apenas para o diretório atual.

Por exemplo, a substituição será substituída /a/b/c/httpdocs/e/f/gpor /a/b/c/httpdocse cddentro desse diretório.

A função precisa estar no seu ambiente de shell atual (como uma função ou alias), pois um processo filho não pode alterar o diretório atual de seu pai. É por isso que digo para colocá-lo no seu .bashrce não em um shell script.

camh
fonte
Aliás, vale a pena mencionar que isso o levará o mais alto possível na hierarquia (o que provavelmente é o caso de uso mais útil).
Ibrahim
3

Você também pode colocar algo assim no seu perfil:

alias cdh='cd $(echo $PWD | sed -e "s/\(.*\/httpdocs\)\/.*/\1/")'

A simples digitação o cdhlevará ao httpdocsdiretório superior do seu caminho atual.

Esteira
fonte
2

Não resolve completamente o seu problema, mas economiza cd ../../../../../../um pouco. Peguei emprestado isso da postagem do usuário desconhecido aqui .


até N

pula N diretórios para cima na árvore de diretórios

Em vez de digitar

cd ../../../..

você apenas digita

up 4

e um

cd -    

vai te trazer de volta

Coloque a função no seu .bashrc para usá-lo.

# (c) 2007 stefan w. GPLv3          
function up {
ups=""
for i in $(seq 1 $1)
do
        ups=$ups"../"
done
cd $ups
}
boehj
fonte