Obteniendo la funcionalidad pushd similar a tcsh dextract en bash

Obteniendo la funcionalidad pushd similar a tcsh dextract en bash

Me encanta bash(versión 4.1.2(1)), pero prefiero la forma en que tcshse implementa pushd +Ncon la dextractopción habilitada, hasta el punto de que me niego a usarla bashcomo mi shell predeterminado por eso. ¿Alguien ha implementado un dextractconjunto de comandos de pila de directorio similar a -o bashtal vez no he descubierto cómo lograr bashque se comporte como tcshsi dextractestuviera habilitado?

El punto conflictivo: el orden en que bashsale la pila de directorios después de un archivo pushd +N. Por ejemplo:

$ cd /tmp
$ pushd a
/tmp/a /tmp
$ pushd ../b
/tmp/b /tmp/a /tmp
$ pushd ../c
/tmp/c /tmp/b /tmp/a /tmp
$ pushd +1
/tmp/b /tmp/a /tmp /tmp/c

¿Por qué bash(y por defecto tcsh) rota las posiciones de todos los demás directorios cuando hago un pushd +1? ¿Por qué es esto útil? (Quizás si alguien me lo explicara, podría apreciar el comportamiento y acostumbrarme a él). Compárelo con tcshwith dextract, que simplemente lo extrae y lo coloca encima:

% set dextract
% cd /tmp
% pushd a
/tmp/a /tmp 
% pushd ../b
/tmp/b /tmp/a /tmp 
% pushd ../c
/tmp/c /tmp/b /tmp/a /tmp 
% pushd +1
/tmp/b /tmp/c /tmp/a /tmp 

Tenga en cuenta que el orden restante de los directorios no se modifica. Considero que esto es importante porque es más fácil realizar un seguimiento en mi mente cuando el orden no se rota, y así no tengo que estar siempre dirsbuscando el directorio que quiero.

Si tuviera que intentarlo, ¿por dónde empezaría? Veo que hay una variable DIRSTACK, pero no es correcta (está vacía cuando la pila tiene cuatro entradas), aunque cambiarla altera la pila (aunque no correctamente).

Respuesta1

Después de un poco de trabajo e inspiración, resolví mi problema:

# dextract-like pushd -- push $1'st directory to top of stack and shift rest down
function pushd {
    local t
    if [[ $1 =~ ^[-+]?[0-9]+$ ]]; then
        pos=$1
        [[ ${pos} -lt 0 ]] && ((pos=${#DIRSTACK[@]}+${pos}))
        if [[ ${pos} -gt 0 && ${pos} -lt ${#DIRSTACK[@]} ]]; then
            t="${DIRSTACK[$pos]}"
            # This is crufty. You can't put ~ in DIRSTACK, except the
            # shell will put it into position zero when it refers to your
            # own directory (not anyone else's!). So replace any occurrences.
            DIRSTACK=("" "${DIRSTACK[0]/#~/${HOME}}" "${DIRSTACK[@]:1:${pos}-1}" "${DIRSTACK[@]:${pos}+1}")
            cd "$t"
            builtin dirs -v
        else
            echo "$0: pushd: $1: directory stack index out of range" 1>&2
        fi
    else
        builtin pushd "$@" >/dev/null || return
        cd .
        builtin dirs -v
    fi
}

información relacionada