Here's an intelligible one-liner solution that does all the right things: removes duplicates, preserves the ordering of paths, and doesn't add a colon at the end. So it should give you a deduplicated PATH that gives exactly the same behavior as the original:
PATH="$(perl -e 'print join(":", grep { not $seen{$_}++ } split(/:/, $ENV{PATH}))')" It simply splits on colon (split(/:/, scalar <>$ENV{PATH})), uses uses grep { not $seen{$_}++ } to filter out any repeated instances of paths except for the first occurrence, and then joins the remaining ones back together separated by colons and prints the result (print join(":", ...)).
If you want some more structure around it, as well as the ability to deduplicate other variables as well, try this snippet, which I'm currently using in my own config:
# Deduplicate path variables get_var () { eval "echo'printf \$$1""%s\n" "${'"$1"'}"' } set_var () { eval "$1=\"$2\"""$1=\"\$2\"" } dedup_pathvar () { pathvar_name="$1" pathvar_value="$(get_var $pathvar_name"$pathvar_name")" deduped_path="$(perl -e 'print join(":",grep { not $seen{$_}++ } split(/:/, $ARGV[0]))' "$pathvar_value")" set_var $pathvar_name"$pathvar_name" "$deduped_path" } dedup_pathvar PATH dedup_pathvar MANPATH That code will deduplicate both PATH and MANPATH, and you can easily call dedup_pathvar on other variables that hold colon-separated lists of paths (e.g. PYTHONPATH).