This function should remove dups.
dedup(){
declare -a new=() copy=("${DIRSTACK[@]:1}")
declare -A seen
local v i
seen[$PWD]=1
for v in "${copy[@]}"
do if [ -z "${seen[$v]}" ]
then new+=("$v")
seen[$v]=1
fi
done
dirs -c
for ((i=${#new[@]}-1; i>=0; i--))
do builtin pushd -n "${new[i]}" >/dev/null
done
}
It copies the list of dirs, except the first which is bogus, into an array copy
, and for each dir adds it to a new
array if we have not already seen
it (an associative array). This ensures older dup entries, which are later in the array, are not copied.
The dir list is cleared, and the array is then pushd
in reverse order.
The first bogus element of the dirs list is the current directory, which is unchanged. It is set in the seen
array at the start to also get it removed if earlier in the dir list.
If you want to do this automatically, you can override pushd
eg:
pushd(){
builtin pushd "$@"
dedup
}
setopt pushd_ignore_dups
makes this systematic.