Avons-nous plus d'histoire pour le cd?

Réponses:

31

La commande que vous recherchez est pushdet popd.

Vous pouvez voir un exemple pratique de travail d' icipushd et popdd'ailleurs .

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
Ramesh
la source
1
Il existe également des $OLDPWDcas où vous souhaitez basculer entre deux répertoires à l'aide de la même commande, mais je ne sais pas si c'est spécifique à un shell et à une distribution / un noyau.
mechalynx
4
@ivy_lynx OLDPWDexiste dans tous les shells POSIX, mais il est inutile pour cette question qui demande comment aller au-delà (la question mentionne déjà cd -ce qui est un raccourci pour cd "$OLDPWD").
Gilles 'SO- arrête d'être méchant'
2
Y a-t-il une raison que vous utilisez cd /tmp/dir1; pushd . au lieu de juste pushd /tmp/dir1?
GnP
@gnp, pas de raison spécifique. Cela vient juste du lien que j'ai mentionné dans la réponse. pushd /tmp/dir1devrait fonctionner très bien.
Ramesh
1
Ok, juste choisi ma curiosité. J'aimerais vous suggérer d'améliorer votre réponse avec un exemple concret en utilisant pushdet popden parcourant une arborescence de répertoires. Votre réponse est déjà la bonne.
GnP
54

Vous n'avez pas spécifié le shell que vous utilisez, laissez donc cela être une excuse pour annoncer zsh.

Oui, nous avons plus d’historique pour cd, à savoir cd -2, cd -4etc. Ce qui est très pratique cd -TAB, notamment avec le système de complétion et les couleurs activées:

Voici ce que j'ai dans .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'

Et le résultat:

entrez la description de l'image ici

Jimmij
la source
4
bash bash bash bash
Tim
7
OK, je ne supprimerai pas cette réponse, cela sera peut-être utile pour les autres.
jimmij
23
À moins que la question ne le demande spécifiquement bash, c'est une réponse valable. Ne l'enlève pas.
Liori
Et si le PO modifie sa question pour inclure bash uniquement, cette réponse sera-t-elle toujours valable?
Ooker
3
Cela vaut la peine de mentionner que, mis à part setopt AUTO_PUSHD, aucune des configurations ci-dessus n'est nécessaire pour obtenir une pile de répertoires omniprésente avec achèvement en stock zsh. PUSHD_MINUSinverse le sens de cd +et cd -(une question de goût), CDABLE_VARSn’est pas pertinent pour les piles de répertoires et l’ zstyleinvocation donnée ici ajoute simplement une couleur à la sortie d’un achèvement de pile de répertoires. Il faut cependant initialiser le sous-système de complétion avec autoload -U compinit && compinit.
wjv
13

Pour répondre à votre question concernant "plus d'histoire". Non, la cd -fonctionnalité de Bash ne prend en charge qu'un seul répertoire vers lequel vous pouvez "retourner". Comme le dit @Ramesh dans sa réponse. Si vous souhaitez un historique plus long des répertoires, vous pouvez utiliser pushdet popdenregistrer un répertoire ou en revenir à un précédent.

Vous pouvez également voir la liste de ce qui est actuellement dans la pile avec la dirscommande.

Vous trouverez une explication détaillée à partir de cette réponse intitulée: Comment utiliser les commandes pushd et popd? .

slm
la source
J'ai inclus une référence de votre réponse. J'espère que ça ne vous dérange pas. :)
Ramesh
@Ramesh - Nope allez-y.
slm
8

Vous pouvez installer et utiliser mon utilitaire de répertoire pour Bash.

En gros, il s’agit d’un démon qui collecte les modifications de répertoires de tous vos shells et d’un programme Cdk qui affiche l’historique et vous permet de choisir n’importe quel répertoire dans lequel basculer (pour que vous ne soyez pas limité à une pile).

cjm
la source
7

Vous avez autant d'histoire que vous voulez:

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"
}

C'est une fonction shell qui devrait permettre à tout shell compatible POSIX d'offrir un historique de zshstyle cd. Il fait tout son travail sans faire appel à un seul sous-shell, et je pense que son flux est assez sain - il semble traiter tous les cas correctement avec des tests modérés.

La fonction tente de jouer aussi bien avec son environnement qu’elle peut le faire tout en s’appuyant sur une syntaxe entièrement portable: elle ne fait qu’une hypothèse, à savoir que la $DIRSTACKvariable d’environnement est sa propriété à utiliser à sa guise.

Il canonise tous les chemins qu'il stocke $DIRSTACKet les sérialise entre guillemets simples - même s'il garantit que chacun d'entre eux est bien cité et sérialisé avant de l'ajouter à la valeur de la variable et qu'il ne devrait pas y avoir de problème avec les caractères spéciaux, quels qu'ils soient. . Si la $DIRSTACKMAXvariable d'environnement est définie, elle l'utilisera comme limite supérieure pour le nombre de chemins conservés dans l'historique, sinon la limite est un.

Si vous chargez la fonction, vous serez cdcomme d'habitude, mais pourrez également cd -[num]revenir à l'historique de votre répertoire de modifications.

Le mécanisme principal de la fonction est cdlui-même - et les ${OLD,}PWDvariables d'environnement. POSIX spécifie de les cdmodifier pour chaque déplacement de chemin - et ceci utilise donc uniquement les variables intégrées du shell et enregistre les valeurs aussi longtemps que vous le souhaitez.

Mikeserv
la source
@datUser - je savais que quelqu'un avait un dat. vous êtes les bienvenus
mikeserv
4

Le script acd_func.sh fait exactement ce que vous décrivez. Essentiellement, il surcharge la cdfonction et vous permet de taper cd --pour obtenir une liste des répertoires visités précédemment, à partir de laquelle vous pouvez sélectionner un numéro. Je trouve très difficile d’utiliser Bash sans cela, et c’est la première chose que j’installe sur un nouveau système.

Nick Edwards
la source
3

D'autres ont déjà couvert des solutions intéressantes. Il y a quelque temps, j'ai créé ma propre solution à un problème connexe qui pourrait être rapidement modifié pour faire "une histoire simple". Je voulais fondamentalement "étiqueter" quelques répertoires couramment utilisés, et je voulais que tous les shells ouverts les voient et persistent entre les redémarrages.

#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
}

En fait , je venais de faire label fooappeler le répertoire courant foo, puis de quelque coquille, goto foowhould cddirectement là - bas. Argument vide: labelcréerait une cible par défaut pour goto.

Je n'ai pas pris la peine d'implémenter la suppression automatique des alias, mais sinon, je l'utilise toujours sous une forme légèrement modifiée.

orion
la source
2

Vous pouvez utiliser ma fonction "cd history" de http://fex.belwue.de/fstools/bash.html

Il se souvient de chaque répertoire où vous avez été et avec "cdh" vous verrez une liste des 9 derniers répertoires. Entrez simplement le numéro et vous êtes de retour dans ce répertoire.

Exemple:

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 / home / framstag
sélectionnez: 4
framstag @ wupp: / tmp / 135_pana / 1280:

cdh fonctionne avec autocd aka "cd sans cd": vous n'avez pas à taper cd ou pushd.

Framstag
la source
2

J'aimerais vous recommander ma fonction 'cd' étendue:

https://github.com/dczhu/ltcd

entrez la description de l'image ici

Il offre les fonctionnalités suivantes pour vous simplifier la vie:

  • Liste globale des répertoires, qui affiche les répertoires récemment visités à partir de tous les onglets / fenêtres du terminal.
  • Liste des répertoires locaux, qui est locale à la session actuelle du shell.
  • Les deux listes prennent en charge la navigation rapide en utilisant j / k (aller en bas / haut), les nombres et la recherche par mot.
  • Saut libre global (par exemple, "cd dir" ou "cd ar" pour aller à / path / to / foo / bar / directory /).
Treulz
la source
Hm, semble prometteur. Je vérifierai.
ddnomad
1

pour bash , en gros: au lieu d'utiliser cd, utilisez pushdpour changer de répertoire, donc ils sont sauvegardés (ce qui signifie empilés)

pushd /home; pushd /var; pushd log

Pour voir l'utilisation de la pile dirset pour faciliter la navigation (pour obtenir les numéros des "entrées de pile", utilisez:

dirs -v

Sortie:

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

Maintenant, utilisez ces chiffres avec cdet ~comme:

cd ~1

Mais maintenant, ces numéros sont réarrangés et la position "0" va changer, il suffit donc de placer pushdle répertoire à la position la plus haute deux fois (ou d'utiliser un mannequin à la position 0) comme:

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

maintenant 1..3 maintiendra sa position. Je lis ceci quelque part mais je ne le sais plus, donc désolé de ne pas donner crédit

(pour libérer le répertoire en cours de la pile / le supprimer de l'utilisation de l'historique popd)

Eli
la source
1

Reportez-vous à la fonction cdh dans "Programmation Shell, 4e" à la page 336. Elle conserve l'historique dans un tableau.

Voici une version plus avancée: https://drive.google.com/open?id=0B4f-lR6inxQWQ1pPZVpUQ3FSZ2M

Stocke l’historique dans le fichier CDHISTFILE et permet de passer au répertoire le plus récent contenant une chaîne, par exemple:

cd -src

Il s’installe par-dessus la commande cd existante en effectuant une alias cd=_cd

utilisateur2251295
la source
1

Je voulais juste ajouter des marques fzf comme solution possible.

Une fois installé, il vous donne les commandes mark and jump pour ajouter et rechercher des répertoires favoris (oui, ce n’est pas exactement l’historique complet, seulement ceux que vous avez ajoutés vous-même).

Le problème que j'ai avec pushd / popd it comportement spécifique à la session, c'est-à-dire j'aimerais avoir la même pile sur différentes sessions bash ou à peu près, ce qui est possible pour les marques fzf.

Sebastian Müller
la source
0

J'ai essayé la réponse donnée par @mikeserv, mais cela n'a pas fonctionné pour moi. Je ne savais pas comment le réparer, alors je viens d'écrire le mien:

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[@]}}")
}

Ceci est également disponible en tant que Gist GitHub . Pour l'utiliser, il vous suffit de coller la fonction dans votre .bashrcou similaire, et vous pourrez faire des choses comme cd -5revenir au 5ème répertoire dans lequel vous vous êtes trouvé. cd -hCela vous donnera un aperçu de votre historique.

saagarjha
la source