Відповіді:
Команда, яку ви шукаєте, є 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
$OLDPWDна випадок, коли ви хочете переходити між двома каталогами, використовуючи одну і ту ж команду, але я не впевнений, наскільки це специфічно для оболонки та дистрибутива / ядра.
OLDPWDіснує у всіх оболонках POSIX, але це марно для цього питання, яке задається питанням, як вийти за рамки цього питання (вже вказується, cd -що є ярликом cd "$OLDPWD").
cd /tmp/dir1; pushd . замість просто pushd /tmp/dir1?
pushd /tmp/dir1повинен працювати просто чудово.
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'
І результат:

bash, це правильна відповідь. Не видаляйте його.
setopt AUTO_PUSHD, жодна з перерахованих настройок не потрібна . PUSHD_MINUSповертає почуття cd +та cd -(питання смаку), CDABLE_VARSне має значення для стеків каталогів, а zstyleвиклик, наведений тут, просто додає забарвлення виводу завершення стека каталогу. Однак потрібно ініціалізувати підсистему завершення autoload -U compinit && compinit.
Щоб відповісти на ваше запитання щодо "додаткової історії". Жодна cd -функція в Bash не підтримує лише одну директорію, до якої можна "перевернути" назад. Як стверджує @Ramesh у своїй відповіді. Якщо вам потрібна довша історія каталогів, ви можете використовувати pushdта popdзберегти каталог або повернутися до попереднього.
Ви також можете побачити список того, що зараз знаходиться в стеку з dirsкомандою.
Детальне пояснення можна знайти з цієї відповіді під назвою: Як використовувати команди pushd та popd? .
У вас стільки історії, скільки ви хочете:
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змінювати їх для кожного переміщення шляху - і таким чином, це просто використовує вбудовані змінні оболонки і зберігає значення стільки часу, скільки вам подобається.
Acd_func.sh скрипт робить саме те , що ви описуєте. По суті, вона перевантажує cdфункцію і дає змогу вводити cd --список попередньо відвіданих каталогів, з яких ви можете вибрати номер. Мені дуже важко використовувати bash без цього, і це перше, що я встановлюю на новій системі.
Інші вже висвітлювали деякі цікаві рішення. Деякий час тому я створив власне рішення пов'язаної проблеми, яку можна було б швидко змінити, щоб зробити "пряму історію". Я в основному хотів "позначити" кілька часто використовуваних каталогів, і хотів, щоб усі відкриті оболонки бачили їх, і щоб вони зберігалися між перезавантаженнями.
#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.
Я не переймався впровадженням автоматизованого видалення псевдонімів, але в іншому випадку я все ще використовую це в дещо зміненому вигляді.
Ви можете використовувати мою функцію "Історія cd" з http://fex.belwue.de/fstools/bash.html
Він запам'ятовує кожен каталог, де ви були, і з "cdh" ви побачите список останніх 9 каталогів. Просто введіть номер і ви знову в цьому каталозі.
Приклад:
framstag @ wupp: /: cdh 1: / usr / local / bin 2: / вар 3: / 4: / tmp / 135_pana / 1280 5: / tmp / 135_pana 6: / tmp / weihnachtsfeier 7: / тмп 8: / місцевий / домашній / фрамстаг виберіть: 4 framstag @ wupp: / tmp / 135_pana / 1280:
cdh працює з autocd aka "cd without cd": вам не потрібно вводити cd або pushd.
Я б рекомендував вам розширити функцію 'cd':
Він забезпечує наступні функції для полегшення життя:
для bash , в основному: замість того, щоб використовувати cd pushdдля зміни Directorys, вони зберігаються (мається на увазі стеки)
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)
Дивіться функцію cdh у "Програмуванні оболонки, 4e" на сторінці 312. Вона зберігає історію в масиві.
Ось більш вдосконалена версія: https://drive.google.com/open?id=0B4f-lR6inxQWQ1pPZVpUQ3FSZ2M
Він зберігає історію у файлі CDHISTFILE і дозволяє перейти до останнього каталогу, що містить рядок, наприклад,
cd -src
Він встановлюється над існуючою командою cd, виконуючи an alias cd=_cd
Просто хотілося додати fzf-позначки як можливе рішення.
Після встановлення він дає вам команду відмітити і перейти, щоб додати та шукати каталоги в закладках (так, це не зовсім повна історія, лише ті, які ви додали до закладок).
Проблема, з якою у мене виникає конкретна поведінка сеансу pushd / popd, тобто я хотів би мати однаковий стек на різних сесіях bash або так, що можливо для fzf-знаків.
Я спробував відповідь, яку дав @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Дасте вам огляд вашої історії.