¿Tenemos más historia para cd?


Respuestas:


31

El comando que está buscando es pushdy popd.

Puede ver un ejemplo práctico de trabajo desde pushdy popddesde aquí .

mkdir /tmp/dir1
mkdir /tmp/dir2
mkdir /tmp/dir3
mkdir /tmp/dir4

cd /tmp/dir1
pushd .

cd /tmp/dir2
pushd .

cd /tmp/dir3
pushd .

cd /tmp/dir4
pushd .

dirs
/tmp/dir4 /tmp/dir4 /tmp/dir3 /tmp/dir2 /tmp/dir1

1
También hay $OLDPWDen caso de que desee alternar entre dos directorios con el mismo comando, pero no estoy seguro de cómo es esto específico de shell y de distribución / kernel.
— mechalynx

44
@ivy_lynx OLDPWDexiste en todos los shells POSIX, pero es inútil para esta pregunta que pregunta cómo ir más allá (la pregunta ya menciona cd -cuál es un atajo para cd "$OLDPWD").
— Gilles 'SO- deja de ser malvado'

2
¿Hay alguna razón que usas en cd /tmp/dir1; pushd . lugar de solo pushd /tmp/dir1?
— GnP

@gnp, no hay razón específica. Fue tomado del enlace al que me he referido en la respuesta. pushd /tmp/dir1debería funcionar bien.
— Ramesh

1
Ok, acabo de recoger mi curiosidad. Me gustaría sugerirle que mejore su respuesta con un ejemplo real usando pushdy popdpara recorrer un árbol de directorios de un lado a otro. Tu respuesta ya es la correcta.
— GnP

54

No especificó qué shell está utilizando, así que deje que esto sea una excusa para anunciar zsh.

Sí, tenemos más historial para cd, a saber cd -2, cd -4etc. Es muy conveniente cd -TAB, especialmente con el sistema de terminación y los colores habilitados:

Esto es lo que tengo en .zshrc:

setopt AUTO_PUSHD                  # pushes the old directory onto the stack
setopt PUSHD_MINUS                 # exchange the meanings of '+' and '-'
setopt CDABLE_VARS                 # expand the expression (allows 'cd -2/tmp')
autoload -U compinit && compinit   # load + start completion
zstyle ':completion:*:directory-stack' list-colors '=(#b) #([0-9]#)*( *)==95=38;5;12'

Y el resultado:

ingrese la descripción de la imagen aquí


44
bash bash bash bash
— Tim

77
OK, no borraré esta respuesta, tal vez sea útil para otros.
— jimmij

23
A menos que la pregunta pregunte específicamente bash, esta es una respuesta válida. No lo quites.
— liori

¿Qué pasa si el OP edita su pregunta para incluir solo bash, esta respuesta seguirá siendo válida?
— Ooker

3
Cabe mencionar que, aparte de setopt AUTO_PUSHD, no se requiere ninguna de las configuraciones anteriores para obtener una pila de directorios omnipresente con finalización en stock zsh. PUSHD_MINUSinvierte el sentido de cd +y cd -(una cuestión de gustos), CDABLE_VARSes irrelevante para las pilas de directorios, y la zstyleinvocación dada aquí simplemente agrega color a la salida de la finalización de una pila de directorios. Sin embargo, se debe inicializar el subsistema de finalización con autoload -U compinit && compinit.
— wjv

13

Para responder a su pregunta sobre "más historia". No, la cd -función en Bash solo admite un único directorio al que puede "voltear". Como @Ramesh afirma en su respuesta. Si desea un historial más largo de directorios, puede usar pushdy popdguardar un directorio o volver a uno anterior.

También puede ver la lista de lo que está actualmente en la pila con el dirscomando.

Se puede encontrar una explicación detallada de esta respuesta titulada: ¿Cómo uso los comandos pushd y popd? .


He incluido una referencia de su respuesta. Espero que no te importe. :)
— Ramesh

@Ramesh - no, adelante.
— slm

8

Puede instalar y usar mi utilidad dirhistory para bash.

Básicamente, es un demonio que recopila cambios de directorio de todos sus shells, y un programa Cdk que muestra el historial y le permite elegir cualquier directorio para cambiar (por lo que no está limitado a una pila).


7

Tienes tanta historia como quieras:

cd() {
[ "$((${DIRSTACKMAX##*[!0-9]*}0/10))" -gt 0 ] &&
        set -- "$@" "$DIRSTACK"               &&
        DIRSTACK='pwd -P >&3; command cd'     ||
        { command cd "$@"; return; }
_q()    while   case "$1" in (*\'*) :   ;;      (*)
                ! DIRSTACK="$DIRSTACK '$2$1'"   ;;esac
        do      set -- "${1#*\'}" "$2${1%%\'*}'\''"
        done
while   [ "$#" -gt 1 ]
do      case    ${1:---} in (-|[!-]*|-*[!0-9]*) : ;;
        (*)     eval "  set $((${1#-}+1))"' "${'"$#}\""
                eval '  set -- "$2"'" $2"'
                        set -- "${'"$1"'}" "$1"'
        ;;esac; _q "$1"; shift
done
eval "  DIRSTACK=; $DIRSTACK    &&"'
        _q "$OLDPWD"            &&
        DIRSTACK=$DIRSTACK\ $1
        set "$?" "${DIRSTACK:=$1}"'" $1
"       3>/dev/null
[ "$(($#-1))" -gt "$DIRSTACKMAX" ] &&
        DIRSTACK="${DIRSTACK% \'/*}"
unset -f _q; return "$1"
}

Esa es una función de shell que debería permitir que cualquier shell compatible con POSIX ofrezca un historial de zshestilo cd. Hace todo su trabajo sin invocar una sola subshell, y creo que su flujo es bastante sólido: parece manejar todos los casos correctamente bajo pruebas moderadas.

La función intenta jugar tan bien con su entorno como puede mientras sigue confiando en una sintaxis totalmente portátil: solo hace una suposición y es que la $DIRSTACKvariable de entorno es su propiedad para hacer lo que quiera.

Canonicaliza todas las rutas que almacena $DIRSTACKy las serializa en comillas simples, aunque garantiza que cada una se cite y serialice de forma segura antes de agregarla al valor de la variable y no debería tener ningún problema con ningún carácter especial de ningún tipo . Si se establece la $DIRSTACKMAXvariable de entorno, la usará como límite superior para el número de rutas que conserva en el historial; de lo contrario, el límite es uno.

Si carga la función de la cdforma habitual, pero también podrá hacer el cd -[num]retroceso a través de su historial de cambio de directorio.

El mecanismo principal de la función es en cdsí mismo, y las ${OLD,}PWDvariables de entorno. POSIX especifica que cdcambien estos para cada movimiento de ruta, por lo que esto solo usa las variables integradas del shell y guarda los valores durante el tiempo que desee.


@datUser: sabía que alguien tenía un dat. de
— nada


3

Otros ya cubrieron algunas soluciones interesantes. Hace algún tiempo, creé mi propia solución a un problema relacionado que podría modificarse rápidamente para hacer un "historial directo". Básicamente quería "etiquetar" algunos directorios de uso común, y quería que todos los shells abiertos los vieran, y que persistieran entre reinicios.

#dir_labels
#functions to load and retrieve list of dir aliases

function goto_complete {
    unset dir_labels
    declare -A dir_labels
    {
    while read line; do
        ll_pre="${line%% *}"
        ll_dir="${line#* }"
        dir_labels["$ll_pre"]="$ll_dir"
    done
    } < ~/.dir_labels
    unset ll_pre
    unset ll_dir

    local cur possib
    cur="${COMP_WORDS[COMP_CWORD]}"
    possib="${!dir_labels[@]}"
    COMPREPLY=( $(compgen -W "${possib}" -- ${cur}) )
}

complete -F goto_complete goto

function goto {
    unset dir_labels
    declare -A dir_labels
    {
    while read line; do
        ll_pre="${line%% *}"
        ll_dir="${line#* }"
        dir_labels["$ll_pre"]="$ll_dir"
    done
    } < ~/.dir_labels
    unset ll_pre
    unset ll_dir

    if [ $# -gt 0 ]; then
    key="$1"
    else
    key=default
    fi
    target="${dir_labels[$key]}"
    if [ -d "$target" ]; then
    cd "$target"
    echo "goto $key: '$target'"
    else
    echo "directory '$target' does not exist"
    fi
}

function label {
    unset dir_labels
    declare -A dir_labels
    {
    while read line; do
        ll_pre="${line%% *}"
        ll_dir="${line#* }"
        dir_labels["$ll_pre"]="$ll_dir"
    done
    } < ~/.dir_labels
    unset ll_pre
    unset ll_dir

    if [ $# -gt 0 ]; then
    target="$1"
    else
    target="default"
    fi
    dir_labels["$target"]=$PWD
    for i in "${!dir_labels[@]}"; do
    echo "$i ${dir_labels[$i]}"
    done > ~/.dir_labels
}

Básicamente, simplemente haría label foopara llamar al directorio actual foo, y luego desde cualquier shell, goto foodebería estar cddirectamente allí. Argumento vacío: labelcrearía un objetivo predeterminado para goto.

No me molesté en implementar la eliminación automática de alias, pero de lo contrario, todavía estoy usando esto en una forma ligeramente modificada.


2

Puede usar mi función "historial de cd" en http://fex.belwue.de/fstools/bash.html

Recuerda cada directorio donde ha estado y con "cdh" verá una lista de los últimos 9 directorios. Simplemente ingrese el número y regresará a este directorio.

Ejemplo:

framstag @ wupp: /: cdh
1: / usr / local / bin
2: / var
3: /
4: / tmp / 135_pana / 1280
5: / tmp / 135_pana
6: / tmp / weihnachtsfeier
7: / tmp
8: / local / hogar / framstag
seleccione: 4
framstag @ wupp: / tmp / 135_pana / 1280:

cdh funciona con autocd, también conocido como "cd sin cd": no tiene que escribir cd o pushd.


2

Me gustaría recomendarle mi función 'cd' extendida:

https://github.com/dczhu/ltcd

ingrese la descripción de la imagen aquí

Proporciona las siguientes características para facilitarle la vida:

  • Listado global de directorios, que muestra los directorios visitados recientemente desde todas las pestañas / ventanas de terminal.
  • Listado de directorio local, que es local para la sesión de shell actual.
  • Ambos listados admiten navegación rápida mediante el uso de j / k (subir / bajar), números y búsqueda de palabras.
  • Salto libre global (por ejemplo, "cd dir" o "cd ar" para ir a / path / to / foo / bar / directory /).

Hm, parece prometedor. Lo comprobaré.
— ddnomad

1

para bash , básicamente: en lugar de usar el uso de cd pushdpara cambiar los directores, entonces se guardan (lo que significa apilado)

pushd /home; pushd /var; pushd log

Para ver el uso de la pila dirsy para una navegación más fácil (para obtener los números de las "entradas de pila", use:

dirs -v

Salida:

me@myhost:/home$ dirs -v
 0  /home
 1  /var
 2  /tmp

Ahora utilice estos números con cdy ~como:

cd ~1

Pero ahora estos números se reordenan y la posición "0" cambiará, por lo que solo pushdel directorio a la posición superior dos veces (o use un ficticio en la posición 0) como:

me@myhost:/home$ dirs -v
 0  /home
 1  /home
 2  /var
 3  /tmp

ahora 1..3 mantendrá su posición . Leí esto en alguna parte pero ya no lo sé, así que lo siento por no dar crédito

(para liberar el directorio actual de la pila / eliminarlo del uso del historial popd)


1

Consulte la función cdh en "Programación de Shell, 4e" en la página 312. Mantiene el historial en una matriz.

Aquí hay una versión más avanzada: https://drive.google.com/open?id=0B4f-lR6inxQWQ1pPZVpUQ3FSZ2M

Almacena el historial en el archivo CDHISTFILE y permite cambiar al directorio más reciente que contiene una cadena, por ejemplo,

cd -src

Se instala sobre el comando cd existente haciendo un alias cd=_cd


1

Solo quería agregar marcas fzf como una posible solución.

Una vez instalado, le da a los comandos marcar y saltar para agregar y buscar directorios marcados (sí, no es exactamente el historial completo, solo los que marcó usted mismo).

El problema que tengo con el comportamiento específico de la sesión pushd / popd, es decir, me gustaría tener la misma pila en diferentes sesiones de bash o algo así, que es posible para las marcas fzf.


0

Intenté la respuesta que dio @mikeserv, pero no funcionó para mí. No sabía cómo solucionarlo, así que escribí el mío:

cd() {
    # Set the current directory to the 0th history item
    cd_history[0]=$PWD
    if [[ $1 == -h ]]; then
        for i in ${!cd_history[@]}; do
            echo $i: "${cd_history[$i]}"
        done
        return
    elif [[ $1 =~ ^-[0-9]+ ]]; then
        builtin cd "${cd_history[${1//-}]}" || # Remove the argument's dash
        return 
    else
        builtin cd "$@" || return # Bail if cd fails
    fi
    # cd_history = ["", $OLDPWD, cd_history[1:]]
    cd_history=("" "$OLDPWD" "${cd_history[@]:1:${#cd_history[@]}}")
}

Esto también está disponible como GitHub Gist . Para utilizarlo, basta con pegar la función en su .bashrco similares, y usted será capaz de hacer cosas como cd -5ir de nuevo a la 5 ª último directorio que has estado en. cd -hLe dará una visión general de su historia.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.