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

Использование:

VER_URXVT=`urxvt -help 2>&1 | head -n 2`

который совпадает с:

VER_URXVT=$(urxvt -help 2>&1 | head -n 2)

получить первые две строки urxvt справка в VER_URXVT.

Если Вы хотите оценить команду в переменной оболочки, необходимо использовать eval:

VER_URXVT='urxvt -help 2>&1 | head -n 2'
eval $VER_URXVT
42
26.01.2015, 05:42
13 ответов

Команда, которую вы ищете, это 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
31
27.01.2020, 19:35

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

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

8
27.01.2020, 19:35

GNU Bash экспортирует функции оболочки в переменные среды, которые включают определения функций:

$ function foo { echo bar; }
$ export -f foo
$ env | grep -A1 foo
foo=() { echo bar
}

При создании нового экземпляра Bash он ищет переменные среды, соответствующие определенному образцу. Содержимое этих переменных автоматически импортируется как функции оболочки. Как объясняет Стефан Шазелас , поскольку эта функция была введена в Bash 1,03, импорт функций был выполнен просто путем замены = в соответствующей записи в массиве переменных среды и интерпретации результата как определения функции. До исправления , которое фиксировало CVE-2014-6271 , переменная среды интерпретировалась полностью, включая любые команды, которые следуют за фактическим телом функции. Патч вводит два специальных режима для функции parse _ и _ execute () , SEVAL _ FUNCDEF и SEVAL _ ONECMD . При вызове функции с помощью SEVAL _ FUNDEF предполагается предотвращение интерпретации команд, отличных от определений функций. Предполагается, что флаг SEVAL _ ONECMD предотвращает выполнение функции более одной команды.

Специально созданная переменная среды Tavis Ormandy делает что-то немного другое. Он предназначен для запутывания синтаксического анализатора и повреждения буфера, используемого для хранения оцениваемых команд. Остатки переменной среды в буфере изменяют интерпретацию последующей команды . Эта связанная проблема получила идентификатор CVE CVE-2014-7169 .

Составными элементами определения переменной среды X = '() {(a) = >\' являются:

  • () {, который интерпретируется синтаксическим анализатором как начало определения функции

  • (a) = предназначен для того, чтобы запутать анализатор и заставить его оставить остатки переменной среды в буфере

  • >\ является фактической полезной нагрузкой, которая остается в буфере

Цель полезной нагрузки состоит в том, чтобы изменить интерпретацию команды, выполняемой в подслоте, вызываемой sh -c «echo date»; . Это, конечно, предполагает, что /bin/sh является символической ссылкой на bash . Если последовательность команды, указанный как операнд для -c , помещается в буфер, содержимое буфера:

>\[0xA]echo date

[0xA] является символом новой строки ASCII, который обычно действует как разделитель команд, но теперь удаляется \ из полезной нагрузки. В результате содержимое буфера интерпретируется как

>echo date

Поскольку Bash позволяет операторам перенаправления предшествовать командам , это эквивалентно

date > echo 

Это просто приводит к выполнению команды date с ее стандартным выводом, перенаправленным в файл с именем echo . Оставшееся эхо cat не является частью эксплойта,это только показывает, что теперь существует файл с именем echo , содержащий выходные данные date .

Что касается того, почему последовательность (a) = путает синтаксический анализатор в этом случае, то, как представляется, он связан с тем, что он появляется как (неправильно сформированное) определение вложенной функции. Упрощенный вариант эксплойта демонстрирует это более четко:

$ X='() { function a a>\' bash -c echo
$ ls echo
echo
-121--56261-

Легко, вы будете использовать команду join . Не помни наизусть спор. Для получения дополнительной информации см. руководство man join .

-121--244860-

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

Список текущего содержимого стека можно также просмотреть с помощью команды dirs .

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

13
27.01.2020, 19:35

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

И результат:

enter image description here

56
27.01.2020, 19:35

У вас есть столько истории, сколько вам нужно:

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

7
27.01.2020, 19:35

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

#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 foo whould cd прямо там. Пустой аргумент: метка создаст цель по умолчанию для goto .

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

3
27.01.2020, 19:35

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

4
27.01.2020, 19:35

для 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" изменится, поэтому просто переместите каталог в верхнюю позицию дважды (или используйте пустышку в позиции 0), например:

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

now 1..3 сохранит там позицию Я где-то читал это, но больше не знаю, извините за то, что не предоставил кредит

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

1
27.01.2020, 19:35

Вы можете использовать мою функцию "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: /local/home/framstag
select: 4
framstag@wupp:/tmp/135_pana/1280:

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

2
27.01.2020, 19:35

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

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

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

cd -src

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

1
27.01.2020, 19:35

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

https://github.com/dczhu/ltcd

enter image description here

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

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

Intenté la respuesta que dio @mikeserv, pero no funcionó para mí. No pude averiguar cómo solucionarlo, así que simplemente escribí el mío:

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

Esto también está disponible como GitHub Gist . Para usar esto, simplemente pegue la función en su .bashrco similar, y podrá hacer cosas como cd -5para volver al 5 o último directorio en el que ha estado. cd -hle dará una visión general de su historial.

1
27.01.2020, 19:35

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

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

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

1
27.01.2020, 19:35

Теги

Похожие вопросы