ANSWER: My problem was that ${DIRSTACK[0]} holds a literal ~, while ${DIRSTACK[@]:1} will not. When I was calling sort
, I was rearranging the order and then whichever DIRSTACK element ${DIRSTACK[0]} got moved to would not work with pushd +element. I solved this problem by not logging ${DIRSTACK[0]} in my $HOME/.logs/dirstack so that it will never be re-sorted to another index. This bug was reported in October 2017 and will be fixed in some version of bash >4.4.
ORIGINAL QUESTION
So I tried to write a pushd
function that could 1) remove duplicates from pushd
(since bash doesn't have dunique
) and 2) keep the last 10 directories across all terminals, meaning I have to write to a file.
pd() {
if [[ -f "$HOME/.logs/dirstack" ]]; then
dirs -c
s=($(sort "$HOME/.logs/dirstack" | uniq))
for dir in "${s[@]}"; do
pushd -n "$dir" >/dev/null
done
fi
local choice="+$1"
pushd $choice
printf '%s\n' "${DIRSTACK[@]:0:10}" >"$HOME/.logs/dirstack"
}
So, obviously this function is dumb because with the sorting you really don't know what directory you're cd
ing into, but this is closer to a Minimum, Viable, Complete Example to show the problem.
Most of the time, this function does not work, but sometimes it will. On failure, it displays an error like:
j@pc$ pd 2
-bash: pushd: ~/jenkins/docker: No such file or directory
On success, it will correctly to go that directory. Failure is independent of the particular directory used. All of the directories exist and I can pushd ~/jenkins/docker
or cd ~/jenkins/docker
without issue.