Вот окончательное решение (на основе двух предыдущих ответов):
(defun abspath
(path-string)
(uiop:unix-namestring
(uiop:merge-pathnames*
(uiop:parse-unix-namestring path-string))))
uiop:parse-unix-namestring
преобразует строковый аргумент в путь, заменяя ссылки .
и ..
; uiop:merge-pathnames*
переводит относительный путь в абсолютный; uiop:unix-namestring
преобразует путь обратно в строку.
Кроме того, если вы точно знаете, на какой файл указывает путь, вы можете использовать либо:
(uiop:unix-namestring (uiop:file-exists-p path))
or
(uiop:unix-namestring (uiop:directory-exists-p path))
потому что и file-exists-p
, и directory-exists-p
возвращают абсолютные пути (или nil
, если файл не существует).
ОБНОВЛЕНИЕ:
По-видимому, в некоторых реализациях (например, ManKai Common Lisp) uiop:merge-pathnames*
не добавляет часть каталога, если в заданном пути отсутствует префикс ./
(например, если вы подаете ему #P"main.c"
, а не #P"./main.c"
). Итак, более безопасное решение:
(defun abspath
(path-string &optional (dir-name (uiop:getcwd)))
(uiop:unix-namestring
(uiop:ensure-absolute-pathname
(uiop:merge-pathnames*
(uiop:parse-unix-namestring path-string))
dir-name)))
person
AlexDarkVoid
schedule
21.06.2017