Получить полный путь к файлу/каталогу в bash
Иногда в аргументах сценария приходят пути к файлам и каталогам в разнообразных форматах, ну например:
./file1 ~/cat1/cat2/ ../../cat1/file2 justfile cat1/file3
А хочется в каждом случае получить полный путь, скажем, «/home/user/cat1/file». И если второй вариант раскроется оболочкой в полный путь еще до передачи сценарию, то остальные так и останутся с точками и относительными путями.
Есть простое и изящное решение, подсмотренное на каких-то форумах:
absPath=$(readlink -f "$(dirname "$relPath")")/$(basename "$relPath")
Эта штука замечательно работает, но ровно до тех пор, пока мы не передадим ей путь «.», «./», «..» или «../». В таком случае basename "$relPath" выдаст «.» или «..», и мы в результате получим путь, который выглядит, соответственно, как-то вроде «/home/user/cat1/cat2/.» или «/home/user/cat1/cat2/..», который работать-то будет, но выглядит не очень.
Можно, конечно, почистить путь от стоящих в конце точек, но в случае с двумя точками придется еще и удалить предпоследнюю компоненту. Но зачем делать работу самому, если ее за тебя могут сделать другие? Вот такой получился окончательный вариант:
absPath=$(readlink -f $(readlink -f "$(dirname "$relPath")")/$(basename "$relPath"))


Решил посмотреть как оно будет звучать в PowerShell. Получилось так:
$absPath = [System.IO.Path]::GetFullPath( $relPath )
bash и Autotools – феерически корявые, неудобные и полные костылей страшилища. Но, черт возьми, чувствуешь себя настоящим хакером, когда их используешь!
Грустно все это.
Кстати, а как в GetFullPath обстоит дело с символическими ссылками? Они раскрываются в середине пути?
Похоже, никак не обстоит дело – http://stackoverflow.com/questions/1750984/what-is-the-right-way-to-compare-two-filenames-to-see-if-they-are-the-same-file в конце есть коммент, что символические ссылки просто не поддерживаются.
В самом хелпе ничего про ссылки нет http://msdn.microsoft.com/en-us/library/system.io.path.getfullpath.aspx