¿Cuál es una forma rápida de línea de comando para cambiar entre múltiples directorios para la administración del sistema?

46

¿Cuál es una forma rápida de línea de comando para cambiar entre múltiples directorios para la administración del sistema? Quiero decir, puedo usar pushd .y popdalternar, pero ¿qué pasa si quiero almacenar múltiplos y recorrerlos, en lugar de sacarlos permanentemente del fondo de la pila?

Volomike
fuente
$CDPATH¿quizás?
Roaima
66
oh, acabo de enterarme cd -después de buscar en Google instigado por esta pregunta.
Nacht - Restablece a Monica
@Nacht: ¿Cómo navegaste por la estructura del archivo antes?
bote solitario
1
Lo hice en cdtodas partes a mano. Fue doloroso Sin embargo, se utilizó la finalización automática con la tecla de tabulación.
Volomike
1
Tal vez quieras probar za . Extremadamente útil cuando saltas mucho dentro del mismo par de directorios.
Rolf

Respuestas:

28

Uso pushdy luego los nombres especiales para los directorios en su pila de directorios: ~1, ~2, etc.

Ejemplo:

tmp $ dirs -v
 0  /tmp
 1  /tmp/scripts
 2  /tmp/photos
 3  /tmp/music
 4  /tmp/pictures
tmp $ cd ~3
music $ dirs -v
 0  /tmp/music
 1  /tmp/scripts
 2  /tmp/photos
 3  /tmp/music
 4  /tmp/pictures
music $ cd ~2
photos $ cd ~4
pictures $ cd ~3
music $ cd ~1
scripts $ 

La forma más efectiva de usar pushdde esta manera es cargar su lista de directorios, luego agregar un directorio más para que sea su directorio actual, y luego puede saltar entre los números estáticos sin afectar la posición de los directorios en su pila.


También vale la pena señalar que cd -lo llevará al último directorio en el que estuvo. También lo hará cd ~-.

La ventaja de ~-más de simplemente -es que -es específica para cd, mientras que ~-se expande por su cáscara de la misma manera que ~1, ~2, etc. son. Esto es útil cuando se copia un archivo entre rutas de directorio muy largas; p.ej:

cd /very/long/path/to/some/directory/
cd /another/long/path/to/where/the/source/file/is/
cp myfile ~-

Lo anterior es equivalente a:

cp /another/long/path/to/where/the/source/file/is/myfile /very/long/path/to/some/directory/
Comodín
fuente
1
También se puede usarcd -
Volomike
cd -actúa como un Forth DROP DUP, por ejemplo, si uno comienza con el directorio a , con stack abcd , a cd -cambia la pila a bbcd . bashSin embargo, tal vez sea un error, ya que un segundo cd -cambia la pila a abcd . De esto podemos inferir que cd -usa una estructura de datos separada para almacenar el directorio anterior, además de cambiar la pila.
agc
3
@agc, cd -usos $OLDPWDy nada más.
Comodín
Entonces, tal vez cd -fue la característica de bash anterior , luego agregaron una pila, pero temieron romper el código anterior más de lo que querían un diseño más simple. Corrección a la anterior, cd -actúa algo así como un Forth OLDPWD @ SWAP OLDPWD ! DUP . A diferencia cd foo, cd -imprime el nombre del directorio intercambiado.
agc
O siempre está el contenedor interactivo pushd (otras respuestas a esa pregunta incluyen autojump, etc., etc.).
Inútil
42

bashLa función integrada pushdcon las opciones +y -puede rotar la pila de directorios. La sintaxis puede ser un poco confusa, quizás porque esa pila es una matriz basada en cero . Estas funciones de contenedor simples recorren la pila de directorios:

# cd to next     directory in stack (left  rotate)
ncd(){ pushd +1 > /dev/null ; }
# cd to previous directory in stack (right rotate)
pcd(){ pushd -0 > /dev/null ; }

Prueba: configure una pila de cuatro directorios.

dirs -c   # clear directory stack
cd /home ; pushd /etc ; pushd /bin ; pushd /tmp

Ahora / tmp es el directorio actual, y la pila se ve así:

/tmp /bin /etc /home

Cambie al siguiente directorio en la pila, (y muéstrelo), cuatro veces:

ncd ; pwd ; ncd ; pwd ; ncd ; pwd ; ncd ; pwd

Salida:

/bin
/etc
/home
/tmp

Cambie al directorio anterior en la pila, (y muéstrelo), cuatro veces:

pcd ; pwd ; pcd ; pwd ; pcd ; pwd ; pcd ; pwd

Salida:

/home
/etc
/bin
/tmp

Una nota sobre cd -: La respuesta de Wildcard ayudó a ilustrar cómo cd -no se usa la matriz $ DIRSTACK (usa la variable $ OLDPW ), por lo que cd -no afecta a $ DIRSTACK de la forma en que debería hacerlo un intercambio basado en pila. Para corregir eso, aquí hay una simple función de intercambio basada en $ DIRSTACK :

scd() { { pushd ${DIRSTACK[1]} ; popd -n +2 ; } > /dev/null ; }

Prueba:

dirs -c; cd /tmp; \
pushd /bin; \
pushd /etc; \
pushd /lib; \
pushd /home; \
scd; dirs; scd; dirs

Salida:

/bin /tmp
/etc /bin /tmp
/lib /etc /bin /tmp
/home /lib /etc /bin /tmp
/lib /home /etc /bin /tmp
/home /lib /etc /bin /tmp
agc
fuente
Mi frustración es que quiero poner elementos en la pila y mantenerlos allí hasta que decida despejar la pila. De esa manera, puedo empujar, empujar, empujar, y luego recorrer cada uno de los tres directorios según sea necesario. Digamos, por ejemplo, que necesito alternar entre tres directorios como si fueran pestañas del navegador, y avanzar y retroceder hasta que cierre una pestaña. ¿Esto aborda esto en una línea de comando?
Volomike
55
Sí, creo que sí, pruébalo. Para eliminar el elemento superior, haga popd, para eliminarlo sin cambiar los directorios, haga popd -n. Para limpiar la pila, hazlo dirs -c. Lástima que los diseñadores de bash enterraron funciones tan útiles en una sintaxis no intuitiva. Ver man bashdebajo pushd, dirsetc.
agc
¡Trabajos! Y estaba claro como el barro en los documentos. Me gusta su simplicidad, ahora que conozco la técnica.
Volomike
13

Te sugiero que instales fasd . Le brinda la capacidad de saltar rápidamente a cualquier directorio en el que ya haya estado escribiendo solo una pequeña fracción de su nombre.

Ejemplo: si ha visitado /home/someName/scripts/, puede saltar allí simplemente escribiendo, z scrpor ejemplo. Es mucho más conveniente recordar el orden en la pila de historial o algo similar.

kaqqao
fuente
10

Cuando cden alguna parte, Bash almacena el directorio de trabajo de edad una variable de entorno, $OLDPWD.

Puede volver a ese directorio con cd -, que es equivalente a cd "$OLDPWD".

Puede rebotar de un lado a otro entre los directorios de esta manera:

blue$ cd ~/green
green$ cd -
blue$ cd -
green$
RJHunter
fuente
6

Escribí un script llamado xyzzypara hacer esto:

#!/bin/bash

i="$1"
i=$((${i//[^0-9]/}))
i="$(($i-1+0))"

b="$2"
b=$((${b//[^0-9]/}))
b="$(($b-1+0))"

if [ -z "$XYZZY_INDEX" ]; then
    XYZZY_INDEX="$((-1))"
fi

if [ ! -f "/tmp/xyzzy.list" ]; then
    touch /tmp/xyzzy.list
    chmod a+rw /tmp/xyzzy.list
fi
readarray -t MYLIST < /tmp/xyzzy.list

showHelp(){
read -r -d '' MYHELP <<'EOB'
xyzzy 1.0

A command for manipulating escape routes from grues. Otherwise known as a useful system admin
tool for storing current directories and cycling through them rapidly. You'll wonder why this
wasn't created many moons ago.

Usage: xyzzy [options]

help/-h/--help      Show the help.

this/-t/--this      Store the current directory in /tmp/xyzzy.list

begone/-b/--begone  Clear the /tmp/xyzzy.list file. However, succeed with a number and
            it clears just that item from the stored list.

show/-s/--show      Show the list of stored directories from /tmp/xyzzy.list

. #         Use a number to 'cd' to that directory item in the stored list. This syntax is odd:

            . xyzzy 2

            ...would change to the second directory in the list

. [no options]      Use the command alone and it cd cycles through the next item in the stored 
            list, repeating to the top when it gets to the bottom. The dot and space before xyzzy
            is required in order for the command to run in the current shell and not a subshell:

            . xyzzy

Note that you can avoid the odd dot syntax by adding this to your ~/.bashrc file:

  alias xyzzy=". xyzzy"

and then you can do "xyzzy" to cycle through directories, or "xyzzy {number}" to go to a
specific one.

May you never encounter another grue.

Copyright (c) 2016, Mike McKee <https://github.com/volomike>
EOB
    echo -e "$MYHELP\n"
}

storeThis(){
    echo -e "With a stroke of your wand, you magically created the new escape route: $PWD"
    echo "$PWD" >> /tmp/xyzzy.list
    chmod a+rw /tmp/xyzzy.list
}

begoneList(){
    if [[ "$b" == "-1" ]]; then
        echo "POOF! Your escape routes are gone. We bless your soul from the ever-present grues!"
        >/tmp/xyzzy.list
        chmod a+rw /tmp/xyzzy.list
    else
        echo -n "Waving your wand in the dark, you successfully manage to remove one of your escape routes: "
        echo "${MYLIST[${b}]}"
        >/tmp/xyzzy.list
        chmod a+rw /tmp/xyzzy.list
        for x in "${MYLIST[@]}"; do
            if [[ ! "$x" == "${MYLIST[${b}]}" ]]; then
                echo "$x" >> /tmp/xyzzy.list
            fi
        done
    fi
}

showList(){
    echo -e "These are your escape routes:\n"
    cat /tmp/xyzzy.list
}

cycleNext(){
    MAXLINES=${#MYLIST[@]}
    XYZZY_INDEX=$((XYZZY_INDEX+1))
    if [[ $XYZZY_INDEX > $(($MAXLINES - 1)) ]]; then
        XYZZY_INDEX=0
    fi
    MYLINE="${MYLIST[${XYZZY_INDEX}]}"
    cd "$MYLINE";
}

switchDir(){
    MYLINE="${MYLIST[${i}]}"
    cd "$MYLINE";
}

if [[ "$@" == "" ]];
then
    cycleNext
fi;

while [[ "$@" > 0 ]]; do case $1 in
    help) showHelp;;
    --help) showHelp;;
    -h) showHelp;;
    show) showList;;
    -s) showList;;
    --show) showList;;
    list) showList;;
    this) storeThis;;
    --this) storeThis;;
    -t) storeThis;;
    begone) begoneList;;
    --begone) begoneList;;
    *) switchDir;;
    esac; shift
done

export XYZZY_INDEX

La forma en que uso esto es copiar en la /usr/bincarpeta y luego chmod a+xen ella. Luego, edito mi ~/.bashrcarchivo de cuenta raíz y de usuario para incluir estas líneas en la parte inferior:

alias xyzzy='. xyzzy'
alias xy='. xyzzy'

El 'xy' es una forma abreviada del comando para escribir más rápido.

Entonces, puedo almacenar el directorio actual en la lista con ...

xyzzy this

... y repita según sea necesario. Una vez que complete esta lista con los directorios que necesito, permanecerán allí hasta que reinicie la computadora porque es cuando / tmp se borra nuevamente. Entonces puedo escribir ...

xyzzy show

... para enumerar los directorios guardados actualmente. Para cambiar a un directorio, tengo dos opciones. Una opción es especificar la ruta por índice (y es un índice basado en 1) así:

xyzzy 2

... que cambiaría al directorio que es el segundo elemento de la lista. O bien, podría dejar el número de índice y simplemente hacer:

xyzzy

... para que recorra cada directorio como lo necesito. Para más comandos que puede hacer, escriba:

xyzzy help

Por supuesto, el trabajo es más divertido con las tontas declaraciones de eco que agregué.

Tenga en cuenta que xyzzy es una referencia a la aventura de texto Collosal Cave , donde escribir xyzzy le permitiría cambiar entre dos salas en el juego para evitar grues.

Volomike
fuente
2
+1 Empecé a jugar con esto. Es agradable, pero parece fallar si aún no se han agregado directorios e ingresas solo xyzzy. Necesita una prueba más para MAXLINES -eq 0 en cyclenext ().
Joe
5

Utilizo un pequeño script llamado z [link] , que también podría ser de interés, a pesar de que no hace exactamente lo que me pediste.

NAME
       z - jump around

SYNOPSIS
       z [-chlrtx] [regex1 regex2 ... regexn]

AVAILABILITY
       bash, zsh

DESCRIPTION
       Tracks your most used directories, based on 'frecency'.

       After  a  short  learning  phase, z will take you to the most 'frecent'
       directory that matches ALL of the regexes given on the command line, in
       order.

       For example, z foo bar would match /foo/bar but not /bar/foo.
Graipher
fuente
Tal vez me perdí algo, pero ¿dónde encuentro el script z en sí?
Joe
Lo sentimos, el enlace estaba en la z. Se editará para que sea más fácil de ver.
Graipher
5

También hay cd_funcde Petar Marinov, básicamente cdcon un historial de hasta 10 entradas: http://linuxgazette.net/109/misc/marinov/acd_func.html

# do ". acd_func.sh"
# acd_func 1.0.5, 10-nov-2004
# petar marinov, http:/geocities.com/h2428, this is public domain

cd_func ()
{
  local x2 the_new_dir adir index
  local -i cnt

  if [[ $1 ==  "--" ]]; then
    dirs -v
    return 0
  fi

  the_new_dir=$1
  [[ -z $1 ]] && the_new_dir=$HOME

  if [[ ${the_new_dir:0:1} == '-' ]]; then
    #
    # Extract dir N from dirs
    index=${the_new_dir:1}
    [[ -z $index ]] && index=1
    adir=$(dirs +$index)
    [[ -z $adir ]] && return 1
    the_new_dir=$adir
  fi

  #
  # '~' has to be substituted by ${HOME}
  [[ ${the_new_dir:0:1} == '~' ]] && the_new_dir="${HOME}${the_new_dir:1}"

  #
  # Now change to the new dir and add to the top of the stack
  pushd "${the_new_dir}" > /dev/null
  [[ $? -ne 0 ]] && return 1
  the_new_dir=$(pwd)

  #
  # Trim down everything beyond 11th entry
  popd -n +11 2>/dev/null 1>/dev/null

  #
  # Remove any other occurence of this dir, skipping the top of the stack
  for ((cnt=1; cnt <= 10; cnt++)); do
    x2=$(dirs +${cnt} 2>/dev/null)
    [[ $? -ne 0 ]] && return 0
    [[ ${x2:0:1} == '~' ]] && x2="${HOME}${x2:1}"
    if [[ "${x2}" == "${the_new_dir}" ]]; then
      popd -n +$cnt 2>/dev/null 1>/dev/null
      cnt=cnt-1
    fi
  done

  return 0
}

alias cd=cd_func

if [[ $BASH_VERSION > "2.05a" ]]; then
  # ctrl+w shows the menu
  bind -x "\"\C-w\":cd_func -- ;"
fi

Simplemente use cd --para mostrar una lista de los últimos 10 directorios a los que editó cdy cd -N(dónde Nestá el índice de la entrada) para ir allí.

phk
fuente
4

Principalmente uso ZSH con el perfil oh-my-zsh . Puede escribir en una terminal la siguiente coincidencia:

# cd /ho

Luego, simplemente puede usar flechas (arriba y abajo) para recorrer todo el historial de shell que muestra solo aquellas entradas que comienzan con los caracteres anteriores. Entonces, por ejemplo, si fue a /home/morfik/Desktop/y /home/morfik/something/, puede cambiar entre los directorios muy rápido. No importa cuántas entradas en el historial de shell tenga, pero cuando tenga muchas, simplemente use una mejor expresión, es decir, cd /home/morfy aquí presione las flechas arriba / abajo en su teclado.

También hay otra forma de lograr la solución. En este caso, debe usar tmux y FZF . Luego solo crea una tecla de acceso rápido, por ejemplo ctrl-r, y cuando la presiona, su ventana actual se dividirá y verá esto:

ingrese la descripción de la imagen aquí

Ahora puede usar expresiones para buscar en la lista. Acabo de escribir ^cd /media, que devuelve solo las entradas que comienzan con la frase. Por supuesto, puede escribir 'cd 'homepara que coincida con el comando y también con el nombre completo del directorio (no la ruta, solo el nombre):

ingrese la descripción de la imagen aquí

Mikhail Morfikov
fuente
4

Puede lograr esto con un montón de alias en su ~/.bashrc(o equivalente)

El objetivo principal es escribir casi al mínimo (por ejemplo, d5salta al directorio número 5 en el grupo) para cambiar entre directorios en el grupo. También queremos facilitar la adición / eliminación de directorios a / del grupo:

alias pd=pushd
alias po=popd
alias d='dirs -v'
alias d0=d
alias d1='pd +1'
alias d2='pd +2'
alias d3='pd +3'
alias d4='pd +4'
alias d5='pd +5'
alias d6='pd +6'
alias d7='pd +7'
alias d8='pd +8'
alias d9='pd +9'
alias d10='pd +10'
# -- feel free to add more aliases if your typical dir pool is larger than 10

Ahora, cada vez que inserta un directorio en la pila, se agrega al grupo numerado en la posición 0 (el directorio actual) y puede saltar (cambiar directorios) con muy poca escritura ( d<N>) y puede ver su grupo actual numerado en cualquier tiempo simplemente escribiendo d.

Algunos ejemplos de uso de estos alias:

Mostrar el grupo de directorios numerado, (el directorio actual es # 0)

$ d
 0  /tmp
 1  /
 2  /usr

Cambiar entre directorios: usar d<N>

$ d2
$ pwd
/usr

Agregar un nuevo directorio al grupo

$ pd /var/log
$ d
 0  /var/log
 1  /usr
 2  /tmp
 3  /

Salta un poco más:

$ d3
$ pwd
/

$ d3
$ pwd
/tmp

$ d
 0  /tmp
 1  /
 2  /var/log
 3  /usr

Eliminar / abrir el directorio superior (actual) del grupo

$ po
$ d
 0  /
 1  /var/log
 2  /usr
arielf
fuente
2

Si tiene instalado iselect , puede hacer algo como esto:

$ alias dirselect='cd $(iselect -a $(dirs -l -p | sort -u))'
$ dirselect

Esto le proporcionará un menú navegable interactivo con teclas de flecha basadas en ncurses en pantalla completa para seleccionar un directorio cd.

Si no ha utilizado pushden la sesión de shell actual, la lista de directorios en el menú comienza con una sola entrada, su directorio actual. Si solo hay una entrada, este dirselectalias solo aparecerá cdsin la pantalla del menú, por lo que efectivamente no hace nada (excepto evitar cd -hacer algo útil)

Para agregar un nuevo directorio a la lista, use pushd dir(o pushd -n dirpara agregar un directorio sin cdtocarlo al mismo tiempo)

Puede rellenar previamente la pushdpila haciendo algo como lo siguiente en su .bashrco ~/.bash_profile:

for d in /var/tmp /tmp /path/to/somewhere/interesting ; do 
  pushd -n "$d" > /dev/null
done

Puede eliminar entradas con popdo popd -n.

Ver help pushd, help popdy help dirsen bash para más información. Y, por supuesto, man iselect.

Por cierto, iselectes probable que esté disponible preenvasado para su distribución. Es para Debian y Ubuntu, etc., y probablemente también para otros.

cas
fuente
2

Si tiene 5 o 10 directorios que usa mucho, y no necesariamente se preocupa por los 5 o 10 directorios usados ​​recientemente , configure algunos alias de comando como

alias cdw="cd /var/www/html" 

Entonces, cuando quiero ir al directorio de la página de inicio de Apache, simplemente escribo cdwcomo respondí en Equivalente de alias para un enlace simbólico. .

Mark Stewart
fuente
2

Estoy usando jump para cambiar rápidamente el directorio de trabajo.

Para agregar el directorio actual:

jump -a [bookmark-name]

Para enumerar todos sus marcadores:

jump -l

p.ej:

------------------------------------------------------------------
 Bookmark    Path                                                 
------------------------------------------------------------------
 reports     ~/mydir/documents/reports
 projects    ~/documents/projects
 dl          ~/Downloads                     
------------------------------------------------------------------

Ahora puede saltar fácilmente a otro directorio:

jump reports

Admite autocompletado para bash y zsh.


Editar (en respuesta a @Joe): el binario jump-binse almacena en /usr/local/bin, y con el script de integración bash (en mi PC ubicado en /var/lib/gems/1.9.1/gems/jump-0.4.1/bash_integration/shell_driver) crea una función bash jumpque llama jump-bin.

un oro
fuente
¿Dónde vive el comando de salto? No lo tengo y no veo de inmediato dónde conseguirlo.
Joe
2

Yo uso aliaspara navegar. Si tiene pocos directorios a los que se accede con frecuencia, simplemente configure los alias. Por ejemplo,

alias e='cd /etc'
alias h='cd /home'
alias al='cd /var/log/apache2/'

Entonces simplemente

e 

le llevará a /etc.

Bestia de seguridad
fuente