У нас есть больше истории для CD?

Ответы:

31

Команда, которую вы ищете, это pushdи popd.

Вы можете просмотреть практический рабочий пример pushdи popdиз здесь .

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
Есть также $OLDPWDслучай, если вы захотите переключаться между двумя каталогами, используя одну и ту же команду, но я не уверен, насколько это относится к оболочке и распределению / ядру.
mechalynx
4
@ivy_lynx OLDPWDсуществует во всех оболочках POSIX, но он бесполезен для этого вопроса, который спрашивает, как выйти за пределы этого (вопрос уже упоминает, cd -что является сокращением cd "$OLDPWD").
Жиль "ТАК - перестань быть злым"
2
Есть ли причина, которую вы используете cd /tmp/dir1; pushd . вместо просто pushd /tmp/dir1?
GnP
@gnp, без особых причин. Это было просто взято по ссылке, на которую я ссылался в ответе. pushd /tmp/dir1должно работать просто отлично.
Рамеш,
1
Хорошо, просто выбрал мое любопытство. Я хотел бы предложить вам улучшить свой ответ с помощью реального примера, использующего pushdи popdдля обхода дерева каталогов взад и вперед. Ваш ответ уже правильный.
GnP
55

Вы не указали, какую оболочку вы используете, поэтому пусть это будет оправданием для рекламы zsh.

Да, у нас больше истории cd, а именно cd -2и cd -4т. Д. Очень удобно cd -TAB, особенно с системой завершения и включенными цветами:

Это то, что я имею в .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'

И результат:

введите описание изображения здесь

jimmij
источник
4
Баш Баш Баш
Тим
7
Хорошо, я не буду удалять этот ответ, может быть, будет полезен для других.
Джимми
23
Если вопрос не задает конкретно bash, это правильный ответ. Не удаляй это.
Лиори
Что, если ОП изменяет свой вопрос, чтобы включить только bash, будет ли этот ответ по-прежнему действительным?
Ooker
3
Возможно, setopt AUTO_PUSHDстоит упомянуть, что, кроме того , ни одна из вышеперечисленных настроек не требуется для получения вездесущего стека каталогов с завершением на складе zsh. PUSHD_MINUSменяет смысл cd +и cd -(вопрос вкуса), не CDABLE_VARSимеет отношения к стекам каталогов, и zstyleприведенный здесь вызов просто добавляет окраску к выводу завершения стека каталогов. Однако необходимо инициализировать подсистему завершения с помощью autoload -U compinit && compinit.
wjv
13

Чтобы ответить на ваш вопрос относительно «больше истории». Никакая cd -функция в Bash не поддерживает только один каталог, который вы можете «перевернуть» обратно. Как @Ramesh заявляет в своем ответе. Если вам нужна более длинная история каталогов, вы можете использовать pushdи, popdчтобы сохранить каталог или вернуться к предыдущему.

Вы также можете увидеть список того, что в данный момент находится в стеке с помощью dirsкоманды.

Подробное объяснение можно найти в ответе: « Как использовать команды pushd и popd? ,

SLM
источник
Я включил ссылку из вашего ответа. Надеюсь, ты не возражаешь. :)
Рамеш
@ Рамеш - Нет, давай.
СЛМ
8

Вы можете установить и использовать мою утилиту dirhistory для bash.

По сути, это демон, который собирает изменения каталогов со всех ваших оболочек, и программа Cdk, которая отображает историю и позволяет вам выбрать любой каталог для переключения (так что вы не ограничены стеком).

CJM
источник
7

У вас столько истории, сколько вы хотите:

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

Это функция оболочки, которая должна позволять любой POSIX-совместимой оболочке предлагать историю в zshстиле cd. Он выполняет всю свою работу, не вызывая ни одной подоболочки, и я полагаю, что его поток довольно хорош - кажется, он правильно обрабатывает все случаи при умеренном тестировании.

Функция пытается играть со своей средой настолько хорошо, насколько это возможно, при этом все еще полагаясь на полностью переносимый синтаксис - она ​​делает только одно предположение, а именно то, что $DIRSTACKпеременная среды является ее свойством, как и будет.

Он канонизирует все пути, в которых он хранит, $DIRSTACKи сериализует их все в одинарных кавычках - хотя он гарантирует, что каждый из них надежно заключен в кавычки и сериализуется перед добавлением его к значению переменной, и не должен иметь проблем с какими-либо специальными символами любого вида. , Если $DIRSTACKMAXпеременная окружения установлена, она будет использовать ее в качестве верхнего предела для числа путей, которые она сохраняет в истории, в противном случае ограничение равно единице.

Если вы загружаете функцию, вы cdкак обычно, но также сможете выполнить cd -[num]возврат к истории изменений каталога.

Основной механизм функции cdсам по себе - и ${OLD,}PWDпеременные окружения. POSIX указывает, что cdих нужно менять при каждом перемещении пути, и поэтому он просто использует встроенные переменные оболочки и сохраняет значения столько, сколько вам нужно.

mikeserv
источник
@datUser - я знал, что у кого-то есть данные. добро пожаловать
mikeserv
4

Сценарий acd_func.sh делает именно то, что вы описываете. По сути, он перегружает cdфункцию и позволяет вам печатать, cd --чтобы получить список ранее посещенных каталогов, из которого вы можете выбирать по номеру. Мне очень трудно использовать bash без этого, и это первое, что я устанавливаю в новой системе.

Ник Эдвардс
источник
3

Другие уже рассказали о некоторых интересных решениях. Некоторое время назад я создал свое собственное решение связанной проблемы, которое можно было быстро изменить, чтобы сделать «прямую историю». Я в основном хотел «пометить» несколько часто используемых каталогов и хотел, чтобы все открытые оболочки видели их и чтобы они сохранялись между перезагрузками.

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

В принципе , я бы просто сделать , label fooчтобы позвонить в текущий каталог foo, а затем из любой оболочки, goto foowhould cdпрямо там. Пустой аргумент: labelсоздаст цель по умолчанию для goto.

Я не удосужился реализовать автоматическое удаление псевдонимов, но в остальном я все еще использую это в слегка измененном виде.

Орион
источник
2

Вы можете использовать мою функцию "cd history" с http://fex.belwue.de/fstools/bash.html

Он запоминает каждый каталог, в котором вы были, и с помощью «cdh» вы увидите список последних 9 каталогов. Просто введите номер, и вы снова в этом каталоге.

Пример:

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: / местный / дом / фрамстаг
выберите: 4
framstag @ wupp: / TMP / 135_pana / 1280:

cdh работает с autocd aka "cd без cd": вам не нужно вводить cd или pushd.

Framstag
источник
2

Я бы хотел порекомендовать вам мою расширенную функцию "cd":

https://github.com/dczhu/ltcd

введите описание изображения здесь

Это обеспечивает следующие функции, чтобы сделать жизнь проще:

  • Глобальный список каталогов, который показывает недавно посещенные каталоги из всех вкладок / окон терминала.
  • Список локальных каталогов, который является локальным для текущего сеанса оболочки.
  • Оба списка поддерживают быструю навигацию с помощью j / k (переход вниз / вверх), чисел и поиска слов.
  • Глобальный свободный прыжок (например, «cd dir» или «cd ar» для перехода в / path / to / foo / bar / directory /).
treulz
источник
Хм, выглядит многообещающе. Я проверю это.
ddnomad
1

для bash , в основном: вместо использования cd используйте pushdдля изменения каталогов, чтобы они сохранялись (то есть сложены)

pushd /home; pushd /var; pushd log

Чтобы увидеть использование стека dirsи для более удобной навигации (чтобы получить номера «записей стека», используйте:

dirs -v

Выход:

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

Теперь используйте эти числа с cdи ~как:

cd ~1

Но теперь эти числа теперь переставлены, и позиция «0» изменится, поэтому просто pushdпоместите каталог в верхнюю позицию дважды (или используйте пустышку в позиции 0), например:

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

сейчас 1..3 сохранит там положение, я где-то читал, но больше не знаю, так что извините за то, что не дал кредит

(чтобы освободить текущий каталог из стека / удалить его из истории использования popd)

Eli
источник
1

См. Функцию cdh в «Программирование оболочки, 4e» на странице 312. Она хранит историю в массиве.

Вот более продвинутая версия: https://drive.google.com/open?id=0B4f-lR6inxQWQ1pPZVpUQ3FSZ2M

Хранит историю в файле CDHISTFILE и позволяет перейти на самый последний каталог, содержащий строку, например,

cd -src

Он устанавливает себя поверх существующей команды cd, выполнив alias cd=_cd

user2251295
источник
1

Просто хотел добавить fzf-mark как возможное решение.

После установки он дает вам команды пометить и перейти к добавлению и поиску закладок в каталогах (да, это не совсем полная история, только те, которые вы добавили в закладки сами).

Проблема, которую я имею с pushd / popd, это специфичное для сессии поведение, то есть я хотел бы иметь один и тот же стек в другой сессии bash или около того, что возможно для fzf-mark.

Себастьян Мюллер
источник
0

Я попробовал ответ, который дал @mikeserv, но он мне не помог. Я не мог понять, как это исправить, поэтому я просто написал свой собственный:

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

Это также доступно как GitHub Gist . Чтобы использовать это, просто вставьте функцию в свою .bashrcили аналогичную, и вы сможете сделать что-то вроде cd -5возврата к 5- му последнему каталогу, в котором вы были. cd -hОн даст вам обзор вашей истории.

saagarjha
источник