Bash CD hasta en cierta carpeta

16

Trabajo mucho en Magento, y muchas de las personas con las que trabajo, y es molesto tener que escribir:

discos compactos ../../../../../../

Para descubrir que todavía tiene algunos directorios de su carpeta raíz 'httpdocs', entonces estoy tratando de hacer un script que siga este pseudocódigo:

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

Parece bastante simple, supongo que tendría que hacer algún tipo de grep para verificar si la última parte del directorio de trabajo actual es httpdocs, si no, simplemente continúe subiendo un nivel hasta que sea cierto.

He estado buscando aprender bash para esto, aunque parece que ya debe haber algo similar que sea similar, y la sintaxis me desconcierta.

usuario652650
fuente

Respuestas:

8

Esto tiene que ser una función de shell , no un script, porque un script se ejecuta en un nuevo shell (y, por lo tanto, no puede cambiar el directorio del shell original).

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

Por supuesto, puede nombrar la función como desee.

Alguna explicación: La primera prueba ( $PWD != '/') es a prueba de fallas en caso de que no lo haga cdrootcuando no esté dentro de una carpeta httpdocs. Se detendrá cuando llegues a la raíz.

La segunda prueba ( ${PWD##*/} != 'httpdocs') es un poco más complicada. $PWDes una variable que contiene la ruta del directorio actual. ${PWD##*/}recorta todo hasta la última barra inclinada.

cjm
fuente
La desventaja de este iterativo es que pierdes tu capacidad de hacer un poco más cd -tarde para volver a donde estabas.
Ezequiel Muns
27

Tengo una función llamada uptoen mi .bashrc que le permite ir a cualquier directorio en la ruta actual por nombre:

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

También tengo finalización para esta función, de modo que me da nombres de directorio válidos y finalización cuando presiono la pestaña:

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

Además, tengo otra función jdque me permite saltar a cualquier directorio debajo del actual:

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

Ejemplo:

[/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
fuente
También puede agregar un alias para upto httpdocs.
cjm
@drogbane: jdno parece funcionar en todos los casos, ¿te importaría explicar cómo funciona?
Cesar
@Cesar usa globstar ( **). Para habilitar esta función en su uso bash shell shopt -s globstar.
dogbane
2
Esto se hace tan brillantemente que desearía poder votar dos veces.
droope
1
He incluido una detección y activación de compras dinámicas en la jdfunción, consulte gist.github.com/Rob--W/5888648 . Solo lo probé con Bash 4.2.45, así que YMMV.
Rob W
5

La función bash más simple que puedes poner en tu .bashrcque puedo pensar (simple porque no usa bucles o procesos externos) es:

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

Este sistema utiliza la sustitución del modelo de expansión de parámetros para reemplazar todo lo que después /httpdocs/de $PWDla `/ httpdocs'. Se ve muy desordenado porque tenemos que escapar de las barras diagonales en el camino para diferenciarlas de las barras diagonales en la sintaxis de expansión bash. Además, no escape las barras diagonales en la cadena de reemplazo, por lo que también parece inconsistente.

Si no hay ninguna /httpdocs/en la ruta actual, no se realizarán sustituciones y solo cambiará al directorio actual.

Por ejemplo, la sustitución reemplazará /a/b/c/httpdocs/e/f/gcon /a/b/c/httpdocsy cden ese directorio.

La función debe estar en su entorno de shell actual (ya sea como una función o alias) ya que un proceso secundario no puede cambiar el directorio actual de su padre. Es por eso que digo ponerlo en su .bashrcy no en un script de shell.

camh
fuente
Por cierto, vale la pena mencionar que esto lo llevará lo más alto posible en la jerarquía (que de todos modos es el caso de uso más útil).
Ibrahim
3

También podría poner algo como esto en su perfil:

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

Simplemente escribiendo cdhte llevará al httpdocsdirectorio más alto en tu ruta actual.

Estera
fuente
2

No trata completamente su problema, pero ahorrará cd ../../../../../../un poco. He tomado prestado esto de la publicación del usuario desconocido aquí .


arriba N

saltar N directorios hacia arriba en el árbol de directorios

En lugar de escribir

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

solo escribes

up 4

y un

cd -    

te traerá de vuelta

Ponga la función en su .bashrc para usarla.

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