Часто бывает, что длинный путь неправильно набран или вы получаете запись в файле журнала о том, что путь не существует. Есть ли команда или функция оболочки, которая перемещается по иерархии путей, пока не найдет соответствующий путь?
Обмен данными в командной строке может выглядеть следующим образом:
$ ls /var/lib/my/supper/complicated/path
File or directory not found
$ fixpath /var/lib/my/supper/complicated/path
Found /var/lib/my
В качестве бонуса было бы здорово иметь функцию обнаружения сходства:
$ fixpath /var/lib/my/supper/complicated/path
Found /var/lib/my
Did you mean /var/lib/my/super/complicated/path
решение1
$ fixpath /home/user/docus/collection/unix/djakl/jfkdsl/dfjksld/fsdkl
Found /home/user/docus/collection/unix
$ type fixpath
fixpath is a function
fixpath ()
{
CURDIR="$PWD";
DIR="$1";
E=1;
while [ $E -eq 1 ]; do
cd "$DIR" 2> /dev/null && {
E=0;
echo Found "$DIR"
} || {
DIR="${DIR%/*}";
DIR="${DIR:-/}"
};
done;
cd "$CURDIR"
}
Автокоррекцию сходства большинство современных оболочек умеют делать сами. По крайней мере bash и zsh умеют.
решение2
Следующая функция оболочки берет имя пути и определяет самую длинную его часть, которая фактически существует. Она делает это, удаляя последний элемент пути из пути, пока путь не станет полностью пустым или не будет соответствовать файлу (или каталогу, или чему-либо еще), который фактически существует.
fixpath () (
pathname="$1"
while [ -n "$pathname" ] && [ ! -e "$pathname" ]; do
pathname=${pathname%/*}
case "$pathname" in
*/*) continue ;;
*) [ -e "$pathname" ] || pathname=''
break
esac
done
printf 'Longest existing path in "%s" is "%s"\n' "$1" "$pathname"
)
Оператор case
необходим для завершения цикла в случае, когда $pathname
не содержится a /
(что означает, что он не будет изменен заменой переменной). Это позволяет избежать бесконечного цикла при некоторых обстоятельствах.
Тестирование:
$ fixpath /home/kk/blaha/123
Longest existing path in "/home/kk/blaha/123" is "/home/kk"
$ fixpath "$HOME/.profile"
Longest existing path in "/home/kk/.profile" is "/home/kk/.profile"
$ fixpath "n"
Longest existing path in "n" is ""