У нас есть больше истории для 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'

И результат:

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


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? ,


Я включил ссылку из вашего ответа. Надеюсь, ты не возражаешь. :)
— Рамеш

@ Рамеш - Нет, давай.
— СЛМ

8

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

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


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их нужно менять при каждом перемещении пути, и поэтому он просто использует встроенные переменные оболочки и сохраняет значения столько, сколько вам нужно.


@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.


2

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

https://github.com/dczhu/ltcd

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

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

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

Хм, выглядит многообещающе. Я проверю это.
— 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)


1

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

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

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

cd -src

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


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Он даст вам обзор вашей истории.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.