Вот решение для bash, которое вам может понравиться. Это сокращает каждую часть пути до самого короткого префикса, который все еще может быть завершен, и использует * вместо .. в качестве заполнителя.
#!/bin/bash
begin="" # The unshortened beginning of the path.
shortbegin="" # The shortened beginning of the path.
current="" # The section of the path we're currently working on.
end="${2:-$(pwd)}/" # The unmodified rest of the path.
end="${end#/}" # Strip the first /
shortenedpath="$end" # The whole path, to check the length.
maxlength="${1:-0}"
shopt -q nullglob && NGV="-s" || NGV="-u" # Store the value for later.
shopt -s nullglob # Without this, anything that doesn't exist in the filesystem turns into */*/*/...
while [[ "$end" ]] && (( ${#shortenedpath} > maxlength ))
do
current="${end%%/*}" # everything before the first /
end="${end#*/}" # everything after the first /
shortcur="$current"
shortcurstar="$current" # No star if we don't shorten it.
for ((i=${#current}-2; i>=0; i--))
do
subcurrent="${current:0:i}"
matching=("$begin/$subcurrent"*) # Array of all files that start with $subcurrent.
(( ${#matching[*]} != 1 )) && break # Stop shortening if more than one file matches.
shortcur="$subcurrent"
shortcurstar="$subcurrent*"
done
begin="$begin/$current"
shortbegin="$shortbegin/$shortcurstar"
shortenedpath="$shortbegin/$end"
done
shortenedpath="${shortenedpath%/}" # strip trailing /
shortenedpath="${shortenedpath#/}" # strip leading /
echo "/$shortenedpath" # Make sure it starts with /
shopt "$NGV" nullglob # Reset nullglob in case this is being used as a function.
Дайте ему длину в качестве первого аргумента и путь в качестве необязательного второго аргумента. Если второй аргумент не указан, используется текущий рабочий каталог.
Это попытается сократить до указанной длины. Если это невозможно, он просто дает кратчайший путь, который он может дать.
С точки зрения алгоритма, это, вероятно, ужасно, но в итоге получается довольно быстро. (Ключ к быстрым сценариям оболочки - избегать подоболочек и внешних команд, особенно во внутренних циклах.)
По замыслу он укорачивается только на 2 или более символов («hom *» - это столько же символов, сколько «home»).
Это не идеально. В некоторых ситуациях он не будет сокращен настолько, насколько это возможно, например, если есть несколько файлов, имена файлов которых имеют префикс (если существуют foobar1 и foobar2, foobar3 не будет сокращен.)