Использование:
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
Команда, которую вы ищете, это 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
Вы можете установить и использовать мою утилиту dirhistory для bash.
По сути, это демон, который собирает изменения каталогов из всех ваших оболочек, и программа Cdk, которая отображает историю и позволяет вам выбрать любой каталог для переключения (так что вы не ограничены стеком).
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
.
Чтобы ответить на ваш вопрос относительно «больше истории». Нет функции cd -
в Bash поддерживает только один каталог, в который можно вернуться. Как утверждает в своем ответе @ Ramesh. Для сохранения каталога или возврата к предыдущему каталогу можно использовать pushd
и popd
.
Список текущего содержимого стека можно также просмотреть с помощью команды dirs
.
Подробное объяснение можно найти из ответа Как использовать команды pushd и popd? .
Вы не указали, какую оболочку вы используете, так что пусть это будет поводом для рекламы 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'
И результат:
У вас есть столько истории, сколько вам нужно:
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
изменяет их для каждого перемещения по пути - так что это просто использует встроенные переменные оболочки и сохраняет значения столько, сколько вам нужно.
Другие уже рассмотрели некоторые интересные решения. Некоторое время назад я создал свое собственное решение связанной проблемы, которое можно было быстро модифицировать для создания «прямой истории». Я в основном хотел «пометить» несколько часто используемых каталогов и хотел, чтобы все открытые оболочки видели их и чтобы они сохранялись между перезагрузками.
#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
.
Я не удосужился реализовать автоматическое удаление псевдонимов, но в остальном я все еще использую это в слегка измененной форме.
Сценарий acd_func.sh делает именно то, что вы описываете. По сути, он перегружает функцию cd
и позволяет набирать cd -
, чтобы получить список ранее посещенных каталогов, из которого вы можете выбирать по номеру. Мне очень трудно использовать bash без этого, и это первое, что я устанавливаю в новой системе.
для 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
)
Вы можете использовать мою функцию "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.
См. функцию cdh в "Программирование оболочки, 4e" на стр. 312. Она хранит историю в массиве.
Вот более продвинутая версия: https://drive.google.com/open?id=0B4f-lR6inxQWQ1pPZVpUQ3FSZ2M
Сохраняет историю в файле CDHISTFILE и позволяет перейти в самый последний каталог, содержащий строка, например,
cd -src
Она устанавливается поверх существующей команды cd, выполняя псевдоним cd=_cd
Я хотел бы порекомендовать вам мою расширенную функцию 'cd':
Она предоставляет следующие функции, облегчающие жизнь:
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 .bashrc
o similar, y podrá hacer cosas como cd -5
para volver al 5 o último directorio en el que ha estado. cd -h
le dará una visión general de su historial.
Просто хотел добавить fzf -отметки как возможное решение.
После установки он дает вам команды отметить и перейти для добавления и поиска каталогов с закладками (да, это не совсем полная история, только те, которые вы добавили в закладки себя ).
Проблема, с которой я столкнулся при работе с pushd/popd, зависит от поведения сеанса, т. е. я хотел бы иметь один и тот же стек в разных сеансах bash или около того, что возможно для меток fzf -.