Мне нравится bash
(4.1.2(1)-release), но я решительно предпочитаю способ tcsh
реализации pushd +N
с dextract
включенной опцией, настолько, что я отказываюсь использовать ее bash
в качестве своей оболочки по умолчанию из-за этого. Кто-нибудь реализовал dextract
набор команд стека каталогов -like bash
или, может быть, я не понял, как заставить bash
вести себя как tcsh
с dextract
включенной?
Камень преткновения: порядок, при котором bash
стек каталогов остается после pushd +N
. Например:
$ cd /tmp
$ pushd a
/tmp/a /tmp
$ pushd ../b
/tmp/b /tmp/a /tmp
$ pushd ../c
/tmp/c /tmp/b /tmp/a /tmp
$ pushd +1
/tmp/b /tmp/a /tmp /tmp/c
Почему bash
(и default tcsh
) меняет позиции всех других каталогов, когда я делаю a pushd +1
? Почему это полезно? (Возможно, если бы кто-то объяснил, я бы оценил такое поведение и привык к нему.) Сравните с tcsh
with dextract
, который просто извлекает его и помещает наверх:
% set dextract
% cd /tmp
% pushd a
/tmp/a /tmp
% pushd ../b
/tmp/b /tmp/a /tmp
% pushd ../c
/tmp/c /tmp/b /tmp/a /tmp
% pushd +1
/tmp/b /tmp/c /tmp/a /tmp
Обратите внимание, что оставшийся порядок каталогов не изменен. Я считаю это важным, поскольку мне легче следить за порядком в голове, когда порядок не меняется, и мне не приходится каждый раз делать dirs
и искать нужный каталог.
Если бы я попытался это сделать, с чего бы я начал? Я вижу, что есть переменная DIRSTACK
, но она неверна (она пуста, когда в стеке четыре записи), хотя ее изменение изменяет стек (хотя и некорректно).
решение1
После некоторой работы и вдохновения я решил свою проблему:
# dextract-like pushd -- push $1'st directory to top of stack and shift rest down
function pushd {
local t
if [[ $1 =~ ^[-+]?[0-9]+$ ]]; then
pos=$1
[[ ${pos} -lt 0 ]] && ((pos=${#DIRSTACK[@]}+${pos}))
if [[ ${pos} -gt 0 && ${pos} -lt ${#DIRSTACK[@]} ]]; then
t="${DIRSTACK[$pos]}"
# This is crufty. You can't put ~ in DIRSTACK, except the
# shell will put it into position zero when it refers to your
# own directory (not anyone else's!). So replace any occurrences.
DIRSTACK=("" "${DIRSTACK[0]/#~/${HOME}}" "${DIRSTACK[@]:1:${pos}-1}" "${DIRSTACK[@]:${pos}+1}")
cd "$t"
builtin dirs -v
else
echo "$0: pushd: $1: directory stack index out of range" 1>&2
fi
else
builtin pushd "$@" >/dev/null || return
cd .
builtin dirs -v
fi
}