it-swarm-es.tech

crear un alias de cd a pushd - ¿es una buena idea?

¿Es una buena idea utilizar el siguiente alias?

cd() {
    pushd $1;
}

en bash?

Creo que esto sería muy útil, ya que luego puedo usar una serie de popds en lugar de solo un cd - una vez.

¿Existe algún caso en el que esto pueda ser un problema?

37
Lazer

Personalmente, tengo estos en mi bashrc y los uso todo el tiempo:

pushd()
{
  if [ $# -eq 0 ]; then
    DIR="${HOME}"
  else
    DIR="$1"
  fi

  builtin pushd "${DIR}" > /dev/null
  echo -n "DIRSTACK: "
  dirs
}

pushd_builtin()
{
  builtin pushd > /dev/null
  echo -n "DIRSTACK: "
  dirs
}

popd()
{
  builtin popd > /dev/null
  echo -n "DIRSTACK: "
  dirs
}

alias cd='pushd'
alias back='popd'
alias flip='pushd_builtin'

Luego puede navegar en la línea de comandos un poco como un navegador. cd cambia el directorio. back va al directorio anterior desde el que cded. Y flip se moverá entre los directorios actual y anterior sin sacarlos de la pila de directorios. En general, funciona muy bien.

El único problema real del que soy consciente es el hecho de que es un conjunto de comandos al que estoy completamente acostumbrado, pero que no existen en la máquina de nadie más. Entonces, si tengo que usar la máquina de otra persona, puede ser un poco frustrante. Si está acostumbrado a usar pushd y popd directamente, no tiene ese problema. Y aunque si solo pones el alias cd no pone popd, no tendrás el problema de que back no existe, todavía tendrás el problema de que cd no hace exactamente lo que espera en otras máquinas.

Sin embargo, me gustaría señalar que su implementación particular de cd no funciona como cd en el sentido de que el cd normal por sí solo irá a su directorio de inicio, pero el suyo no lo hace. La versión que tengo aquí no tiene ese problema. El mío también agrega DIRSTACK al frente de la impresión dirs, pero eso es más una cuestión de gusto personal más que nada.

Entonces, como dije, uso estos alias todo el tiempo y no tengo ningún problema con ellos. Es solo que puede ser un poco frustrante tener que usar otra máquina y luego no encontrarlos allí (lo cual no debería sorprender, pero son una de esas cosas que usa con tanta frecuencia que no piensa en ellos , por lo que el hecho de que no funcionen como está acostumbrado puede resultar sorprendente).

41
Jonathan M Davis

Esta no es una respuesta directa a la pregunta, pero me enamoré de la ventana del historial del directorio en 4DOS. Tanto es así que escribí mi propia versión para Linux (y Cygwin). Nunca he logrado convertirlo en una utilidad fácil de instalar, pero si conoce un Bash Prompt, no debería ser que difícil de poner en marcha. Tu pregunta me inspiró a ponerlo en un repositorio de Git y subirlo a GitHub: dirhistory .

Básicamente, es un demonio que recopila los cambios de directorio de todos sus shells y un programa Cdk que muestra el historial y le permite elegir cualquier directorio al que cambiar (por lo que no está limitado a una pila). Lo encuentro realmente útil y lo tengo vinculado a Ctrl-PageUp, al igual que lo hizo 4DOS. (Incluso parcheé PuTTY para que enviara Ctrl-PageUp a Bash).

7
cjm

Para mí pushd/popd/dirs es casi útil, pero falta. Así que creé un 'contenedor' alrededor de estos llamado 'navd', implementado esencialmente como un conjunto de 20 alias. (Uno de ellos es una función, en realidad). El código está a continuación, pero aquí hay una breve explicación primero. (Una cosa buena sobre "navd" y trabajar en las máquinas de otras personas: hay una forma de "no instalar" para ejecutarlo: como una opción de instalación, simplemente puede pegar los comandos que implementan "navd" en el indicador bash , y durante la duración de esa sesión de bash para esa máquina, navd funcionará. Eso da cero huella en el sistema de archivos, pero es una instalación temporal. Pon esos comandos en .bashrc para una instalación "real", de curso.)

Caracteristicas:

navd <path>;   -- will make that path the current dir AND will add it to the stack
                         AS A BONUS: If a relative path is used, this command is added to history
                         with an absolute path instead. This improves navigation even when only
                         using history ... because very often relative-path commands in history
                         are useless if the command changes the current directory. (After all, you
                         would have to be in the directory the command was originally issued
                         from in order for such a command to work correctly.)
navd           -- shows the stack, with index numbers for convenience
navd0          -- makes the first entry on the stack (read left-to-right) **the current dir**
navd1          -- makes the second entry on the stack (read left-to-right) **the current dir**
.
.
.
navd9          -- makes the tenth entry on the stack (read left-to-right) **the current dir**
navd-1         -- makes the first entry on the stack WHEN READ RIGHT-to-LEFT(!) **the current dir**
.                                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^
.
.
navd-9         -- makes the 9th entry on the stack WHEN READ RIGHT-to-LEFT(!) **the current dir**

Cualquiera de los diecinueve comandos navd <N> rota la pila de modo que el directorio que se convierte en el directorio actual también ahora se muestra al frente de la pila. Los valores positivos <N> encuentran un directorio contando desde la izquierda, con la indexación comenzando en cero. Los valores <N> negativos encuentran un directorio contando desde la DERECHA, con la indexación comenzando en -1. (Esto sigue la convención de cómo se pueden usar los índices de matriz en Java y otros lenguajes).

Nota: Cualquier comando "navd" muestra la misma pila que usa "pushd" y "dirs", pero la muestra SIN la entrada más a la izquierda que "dirs" se mostraría (ya que esa entrada no está realmente en la pila - es el directorio actual y con "dirs" esa entrada más a la izquierda cambia si se ingresa un comando cd). (El comando "cd <path>" no afecta ningún comportamiento de navd aunque ciertamente afecta el comportamiento de pushd/dirs/popd. Además ... me encanta usar "cd -" para volver "atrás" una vez a un directorio del que acabo de navegar, y "cd -" tampoco afecta el comportamiento de navd).

Bono: Puede haber 19 alias más que NO rotan la pila, sino que simplemente cambian de directorio al lugar indicado en la pila.

 nav0 ... nav9   and   nav-1  ... nav-9

Segundo bono: "navh" muestra los comandos navd <path> del historial, para cargar fácilmente la pila con cortar y pegar. (Cada uno se muestra solo una vez, incluso si está en el historial varias veces, y la lista está ordenada. Además, las entradas se pueden colocar en un archivo $ HOME/.navhignore para evitar que esas entradas exactas aparezcan en la lista de navegación).

 navh

Tres comportamientos clave:

  1. Si borra la pila y repite un comando "navd <ruta>" específico, esa ruta irá a la pila. Eso es lo que quiero y espero ... pero pushd no hace eso, coloca el directorio actual del que está navegando FUERA de la pila, por lo que el efecto en la pila es variable (se siente impredecible) cuando repite el comando .

  2. "navd <ruta>" no pondrá la misma ruta en la pila dos veces.

  3. "navd <ruta>" se coloca en el historial de comandos con la ruta absoluta incluso si la relativa se ingresó la ruta para el comando.

Para mí, los últimos tres comportamientos descritos hacen que usar un comando "navd <path>" del historial sea mucho más útil que usar un "pushd <path>" del historial. Realmente puedo reutilizar el historial para ir a lugares. Y cuando lo hago, no "estropeo" mi pila.

Si puedes y quieres entenderlo, puedes cambiar entre usar navd y pushd/dirs/popd. Ambos usan la misma pila; solo con un estilo diferente. Por ejemplo, use "popd" para eliminar cosas de la pila "navd", o use "dirs -c" para borrar la pila navd.

Piense en pushd/dirs/popd como "¿cómo vuelvo sobre mis pasos?".
Piense en navd como "¿cómo puedo mantener un conjunto de directorios favoritos y cambiar fácilmente entre ellos?".

Pegue lo siguiente en una ventana de terminal y podrá comenzar a usar navd inmediatamente durante la duración de esa sesión de terminal. Este es todo el código que hay para esta función.

# Add 1 function and many related aliases for something like "pushd", called "navd". http://unix.stackexchange.com/a/229161
# Think of pushd/dirs/popd as "how do I retrace my steps?".
# Think of navd as "how do I hold on to a set of favorite directories, and easily switch between them?".
# Pseudo-code to explain each part of the "navd" bash function just below:
#              If no arguments to the 'navd' command:
#                  If stack has entries, then print the stack one-line-per-dir with each line numbered.
#                  Else, if stack is empty, automatically run the equivalent of the navh command.
#              Else (there **are** arguments to the 'navd' command):
#                  If arg is '--help' or '/?' then show help.
#                  Else    (arg is assumed to be a path to a directory)
#                      Remember the directory we are starting at
#                      Change to dir given as argument (the "arg-dir"), and do a few chores:
#                      Do not use arg-dir literally ... instead, magically put the **absolute** path we arrived at into history.
#                      Set a flag if the arg-dir is already in the stack.
#                      If the flag is set then just show the stack (on one line), else ADD to stack, ROTATE to end-of-stack, and show the stack.
#                      Change to dir we started at and then back to the arg-dir. This allows "cd -" to go back to dir we started at.
#                  End-If
#              End-If
navd () {
    if [[ $1 == '' ]]; then                             #--no arguments to the 'navd' command
        if dirs +1 >/dev/null 2>&1; then                #------stack has entries
            dirs -p | Perl -ne 'print (-1+$cn++); print "$_"' | grep -v "^-1";
        else                                            #------stack is empty
            echo "The navd stack is empty. Now running 'navh' in case that's helpful. navd --help works."
            if [[ ! -f $HOME/.navhignore ]]; then echo -n ''>>$HOME/.navhignore;fi;diff --new-line-format="" --unchanged-line-format="" <(history | Perl -ne "if (m/^\s*\d+\s+navd [\"~.\/]/) {s/^\s*\d+\s+/  /;s/\/$//;print}" | sort -u) <(cat $HOME/.navhignore | sort -u);echo "cat $HOME/.navhignore # (Has "`grep -c . <(sort -u $HOME/.navhignore)`" unique lines.)"
        fi
    else                                                #--(there **are** arguments to the 'navd' command)
        if [[ $1 == '--help' || $1 == '/?' ]]; then     #------arg is '--help' or '/?'
            echo "The 'navd' functionality is nothing but one bash function and a set of aliases."
            echo "It offers a different style of handy directory navigation than pushd/popd."
            echo "It uses the same 'stack' as pushd. Look in the .bashrc file for details."
            echo "    (Think of pushd/dirs/popd as 'how do I retrace my steps?'."
            echo "     Think of navd as 'how do I remember a set of favorite directories,"
            echo "     and easily switch between them?'.)"
            echo "As of 10/2015, this link has more info: http://unix.stackexchange.com/a/229161"
            echo "Here is the set of navd-related aliases. None need any parameter:"
            alias | grep 'alias nav' | cut -d= -f1 | grep -v '-' | grep -v 'navh'
            alias | grep 'alias nav' | cut -d= -f1 | grep '-'
            echo "alias navh  # The 'navh' alias has nothing to display until a 'navd <path>' is run. Short for nav-history."
            echo "---- To get started, simpy type navd followed by your favorite path. ----"
            echo "---- navd with no param shows stack. nav0 navigates to first on stack. ----"
        else                                            #------(arg is assumed to be a path to a directory)
            mypwd="$PWD"
            cd "$1" >/dev/null;
            history -s `echo "$PWD" | Perl -pe 's/$ENV{'HOME'}/~/;s/ /\\\\ /g;s/^/navd /'`
            myflag=`dirs -p | Perl -pe 's/\n/:/' | Perl -ne '@a=split(":");$pwd=shift(@a);$flag=0;foreach (@a) {if ($_ eq $pwd) {$flag=1}};print $flag'`
            if [[ $myflag == 1 ]]; then dirs -p | Perl -ne "chomp;s/$/ /;print unless ++\$cn==1"; else pushd .>/dev/null; pushd +1>/dev/null; dirs -p | Perl -ne "chomp;s/$/ /;print unless ++\$cn==1"; fi
            cd "$mypwd"; cd "`dirs -l -0`"
        fi
    fi
};
# Aliases for navigating and rotating the "pushd" stack in the style of "navd":
alias navd0='cd "`dirs -l +1`";dirs -p | Perl -ne "chomp;s/$/ /;print unless ++\$cn==1"' # "-l" is dash-L, and expands "~" to denote the home dir. Needed inside back-ticks.
alias navd1='cd "`dirs -l +1`";pushd -n +1;cd "`dirs -l +1`";dirs -p | Perl -ne "chomp;s/$/ /;print unless ++\$cn==1"'
alias navd2='myd=$PWD;cd "`dirs -l +1`";for i in {1..2};do pushd -n +1>/dev/null;cd "`dirs -l +1`";done;cd "$myd";cd "`dirs -l +1`";dirs -p | Perl -ne "chomp;s/$/ /;print unless ++\$cn==1"'
alias navd3='myd=$PWD;cd "`dirs -l +1`";for i in {1..3};do pushd -n +1>/dev/null;cd "`dirs -l +1`";done;cd "$myd";cd "`dirs -l +1`";dirs -p | Perl -ne "chomp;s/$/ /;print unless ++\$cn==1"'
alias navd4='myd=$PWD;cd "`dirs -l +1`";for i in {1..4};do pushd -n +1>/dev/null;cd "`dirs -l +1`";done;cd "$myd";cd "`dirs -l +1`";dirs -p | Perl -ne "chomp;s/$/ /;print unless ++\$cn==1"'
alias navd5='myd=$PWD;cd "`dirs -l +1`";for i in {1..5};do pushd -n +1>/dev/null;cd "`dirs -l +1`";done;cd "$myd";cd "`dirs -l +1`";dirs -p | Perl -ne "chomp;s/$/ /;print unless ++\$cn==1"'
alias navd6='myd=$PWD;cd "`dirs -l +1`";for i in {1..6};do pushd -n +1>/dev/null;cd "`dirs -l +1`";done;cd "$myd";cd "`dirs -l +1`";dirs -p | Perl -ne "chomp;s/$/ /;print unless ++\$cn==1"'
alias navd7='myd=$PWD;cd "`dirs -l +1`";for i in {1..7};do pushd -n +1>/dev/null;cd "`dirs -l +1`";done;cd "$myd";cd "`dirs -l +1`";dirs -p | Perl -ne "chomp;s/$/ /;print unless ++\$cn==1"'
alias navd8='myd=$PWD;cd "`dirs -l +1`";for i in {1..8};do pushd -n +1>/dev/null;cd "`dirs -l +1`";done;cd "$myd";cd "`dirs -l +1`";dirs -p | Perl -ne "chomp;s/$/ /;print unless ++\$cn==1"'
alias navd9='myd=$PWD;cd "`dirs -l +1`";for i in {1..9};do pushd -n +1>/dev/null;cd "`dirs -l +1`";done;cd "$myd";cd "`dirs -l +1`";dirs -p | Perl -ne "chomp;s/$/ /;print unless ++\$cn==1"'
alias navd-1='cd "`dirs -l -0`";pushd -n -0>/dev/null; dirs -p | Perl -ne "chomp;s/$/ /;print unless ++\$cn==1"'
alias navd-2='myd=$PWD;cd "`dirs -l -0`";pushd -n -0>/dev/null;cd "`dirs -l -0`";pushd -n -0>/dev/null;cd "$myd";cd "`dirs -l +1`";dirs -p | Perl -ne "chomp;s/$/ /;print unless ++\$cn==1"'
alias navd-3='myd=$PWD;cd "`dirs -l -0`";for i in {1..3};do pushd -n -0>/dev/null;cd "`dirs -l -0`";done;cd "$myd";cd "`dirs -l +1`";dirs -p | Perl -ne "chomp;s/$/ /;print unless ++\$cn==1"'
alias navd-4='myd=$PWD;cd "`dirs -l -0`";for i in {1..4};do pushd -n -0>/dev/null;cd "`dirs -l -0`";done;cd "$myd";cd "`dirs -l +1`";dirs -p | Perl -ne "chomp;s/$/ /;print unless ++\$cn==1"'
alias navd-5='myd=$PWD;cd "`dirs -l -0`";for i in {1..5};do pushd -n -0>/dev/null;cd "`dirs -l -0`";done;cd "$myd";cd "`dirs -l +1`";dirs -p | Perl -ne "chomp;s/$/ /;print unless ++\$cn==1"'
alias navd-6='myd=$PWD;cd "`dirs -l -0`";for i in {1..6};do pushd -n -0>/dev/null;cd "`dirs -l -0`";done;cd "$myd";cd "`dirs -l +1`";dirs -p | Perl -ne "chomp;s/$/ /;print unless ++\$cn==1"'
alias navd-7='myd=$PWD;cd "`dirs -l -0`";for i in {1..7};do pushd -n -0>/dev/null;cd "`dirs -l -0`";done;cd "$myd";cd "`dirs -l +1`";dirs -p | Perl -ne "chomp;s/$/ /;print unless ++\$cn==1"'
alias navd-8='myd=$PWD;cd "`dirs -l -0`";for i in {1..8};do pushd -n -0>/dev/null;cd "`dirs -l -0`";done;cd "$myd";cd "`dirs -l +1`";dirs -p | Perl -ne "chomp;s/$/ /;print unless ++\$cn==1"'
alias navd-9='myd=$PWD;cd "`dirs -l -0`";for i in {1..9};do pushd -n -0>/dev/null;cd "`dirs -l -0`";done;cd "$myd";cd "`dirs -l +1`";dirs -p | Perl -ne "chomp;s/$/ /;print unless ++\$cn==1"'
# BONUS commands (beyond the 20). Aliases for navigating but NOT rotating the "navd" stack:
#      Help in remembering: "navd<#>" does more since it both changes the PWD and rotates the stack, whereas "nav<#>" does less
#            (and has one letter less) since "nav<#>" only changes the PWD. Also "navd<#>" acts like the pushd-related command: dirs
#      There is no "nav" command (with no number) so that there will be no conflict if any program called "nav" is used.
alias nav0='cd "`dirs -l +1`";dirs -p | Perl -ne "chomp;s/$/ /;print unless ++\$cn==1"'
alias nav1='cd "`dirs -l +2`";dirs -p | Perl -ne "chomp;s/$/ /;print unless ++\$cn==1"'
alias nav2='cd "`dirs -l +3`";dirs -p | Perl -ne "chomp;s/$/ /;print unless ++\$cn==1"'
alias nav3='cd "`dirs -l +4`";dirs -p | Perl -ne "chomp;s/$/ /;print unless ++\$cn==1"'
alias nav4='cd "`dirs -l +5`";dirs -p | Perl -ne "chomp;s/$/ /;print unless ++\$cn==1"'
alias nav5='cd "`dirs -l +6`";dirs -p | Perl -ne "chomp;s/$/ /;print unless ++\$cn==1"'
alias nav6='cd "`dirs -l +7`";dirs -p | Perl -ne "chomp;s/$/ /;print unless ++\$cn==1"'
alias nav7='cd "`dirs -l +8`";dirs -p | Perl -ne "chomp;s/$/ /;print unless ++\$cn==1"'
alias nav8='cd "`dirs -l +9`";dirs -p | Perl -ne "chomp;s/$/ /;print unless ++\$cn==1"'
alias nav9='cd "`dirs -l +10`";dirs -p | Perl -ne "chomp;s/$/ /;print unless ++\$cn==1"'
alias nav-1='cd "`dirs -l -0`";dirs -p | Perl -ne "chomp;s/$/ /;print unless ++\$cn==1"'
alias nav-2='cd "`dirs -l -1`";dirs -p | Perl -ne "chomp;s/$/ /;print unless ++\$cn==1"'
alias nav-3='cd "`dirs -l -2`";dirs -p | Perl -ne "chomp;s/$/ /;print unless ++\$cn==1"'
alias nav-4='cd "`dirs -l -3`";dirs -p | Perl -ne "chomp;s/$/ /;print unless ++\$cn==1"'
alias nav-5='cd "`dirs -l -4`";dirs -p | Perl -ne "chomp;s/$/ /;print unless ++\$cn==1"'
alias nav-6='cd "`dirs -l -5`";dirs -p | Perl -ne "chomp;s/$/ /;print unless ++\$cn==1"'
alias nav-7='cd "`dirs -l -6`";dirs -p | Perl -ne "chomp;s/$/ /;print unless ++\$cn==1"'
alias nav-8='cd "`dirs -l -7`";dirs -p | Perl -ne "chomp;s/$/ /;print unless ++\$cn==1"'
alias nav-9='cd "`dirs -l -8`";dirs -p | Perl -ne "chomp;s/$/ /;print unless ++\$cn==1"'
# BONUS command (beyond the 20). Alias for showing 'history' of all navd commands that add to the stack.
#                Can be used in a new terminal session to quickly add recently used dirs to the navd stack.
alias navh='if [[ ! -f $HOME/.navhignore ]]; then echo -n ''>>$HOME/.navhignore;fi;diff --new-line-format="" --unchanged-line-format="" <(history | Perl -ne "if (m/^\s*\d+\s+navd [\"~.\/]/) {s/^\s*\d+\s+/  /;s/\/$//;print}" | sort -u) <(cat $HOME/.navhignore | sort -u);echo "cat $HOME/.navhignore # (Has "`grep -c . <(sort -u $HOME/.navhignore)`" unique lines.)"'
# Note: When 'navd <relative-path>' is used, then by bash-magic the navd command puts 'navd <absolute-path>' into history,
#       instead. This allows the output of "navh" to be useful regardless of the directory that is current when it is run.
#
# BONUS commands (beyond the 20). An even shorter alias for navd. An even shorter alias for navh.
alias nd='navd'
alias nh='if [[ ! -f $HOME/.navhignore ]]; then echo -n "">>$HOME/.navhignore;fi;diff --new-line-format="" --unchanged-line-format="" <(history | Perl -ne "if (m/^\s*\d+\s+navd [\"~.\/]/) {s/^\s*\d+\s+/  /;s/\/$//;print}" | sort -u) <(cat $HOME/.navhignore | sort -u);echo "cat $HOME/.navhignore # (Has "`grep -c . <(sort -u $HOME/.navhignore)`" unique lines.)"'

Estos alias se basan en comandos "bash". Se tiene especial cuidado para preservar el comportamiento normal de "cd -". (La mayoría de las veces uso "cd -" en lugar de molestarme con pushd o navd, porque "cd -" es muy útil para volver al último "lugar" en el que estabas o cambiar entre solo 2 lugares, y funciona en todas partes sin instalación).

Estos comandos pueden, por supuesto, colocarse en el archivo .bashrc para una instalación más permanente de ellos.

1
Dana Forsberg

Aquí hay otra solución que le puede gustar. Escribí esto después de jugar con la solución de @cjm. Utiliza el comando de diálogo para crear un menú de tipo ncurses a partir de la salida de dirs. Al seleccionar un elemento, ese directorio se colocará en la parte superior de la pila y se guardará en él. Esto tiene la ventaja sobre dirhistory de darle a cada emulador de terminal su propio búfer de historial de directorio, y es un poco más fácil de instalar.

Para instalar: Una vez que haya asignado un alias de cd a pushd, instale el diálogo, luego coloque esta función en su bashrc:

dirmenu(){
    dirIter=$(dialog --backtitle 'dirmenu' --clear --cancel-label "Exit" --menu "Please select:" 0 0 0 $(dirs) 3>&2 2>&1 1>&3)
    cmd="builtin cd ~$dirIter"
    eval $cmd
}

Me gusta esto un poco más que ejecutar dirs -v, luego ejecutar otro comando para hacer pop o cd en el directorio que quiero. Los menús de diálogo también se pueden personalizar en gran medida a través de su dialogrc.

Entonces, para responder a su pregunta, sí, creo que el aliasing pushd to cd es una gran idea. Es poco probable que tenga problemas de desbordamiento del búfer si reinicia su máquina con regularidad, al menos para las actualizaciones. Aunque tendría cuidado con el uso de cd al hacer scripts; cd en un bucle while podría causar problemas de desbordamiento del búfer. No estoy seguro de qué controla el tamaño del búfer dirs/pushd.

0
Overdr0ne