Как конвертировать абсолютный путь в относительный в Linux - PullRequest
2 голосов
/ 12 марта 2012

Я хотел бы знать, как можно преобразовать абсолютный путь символической ссылки в относительный на основе заданного каталога (который включает связанный файл) на языке c в ОС Linux (Ubuntu).

Я подумал о поиске подстроки относительного пути, но что, если он уже существует выше в иерархии папки?

Вот более конкретное описание того, что я хочу сделать: Относительный путь:

 folder/folder1/folder2

Абсолютный путь:

/home/giorgos/Desktop/folder/folder1/folder2/a.pdf

изменено на

/home/giorgos/Desktop/myfolder/folder1/folder2/a.pdf

Очевидно, я не могу просто найти и заменить "folder /", рассмотрим этот случай:

/home/giorgos/Desktop/folder/folder/folder/folder1/folder2/a.pdf

Его можно искать как в прямом, так и в обратном направлении, и если его заменить, он все равно дает неправильный вывод Только если бы я знал относительный путь, я мог бы найти абсолютное значение в обратном направлении и заменить его, тогда результат будет правильным:

   /home/giorgos/Desktop/folder/myfolder/folder/folder1/folder2/a.pdf

Ответы [ 3 ]

3 голосов
/ 12 марта 2012

Преобразование пути в относительный - это вопрос сначала просмотра количества базовых атомов, разделяемых между двумя путями, а затем вставки ../ для перемещения назад вверх по дереву перед перемещением вниз по правильной ветви.То есть, переходя от: /foo/bar/some/path к /foo/other/path, вы сначала увидите, что они используют / foo, для перехода вверх к той точке вам нужно 3 ../, превращая относительный путь в /foo/../../../other/path.Здесь есть пример boost :: filesystem для C ++ здесь , за исключением C ++ и boost :: filesystem, то же самое можно сделать в C.

1 голос
/ 12 марта 2012

Если бы я писал этот инструмент, у меня был бы серьезный соблазн принять решение о том, что абсолютные символические ссылки должны иметь то же значение при перемещении в другое место в файловой системе - пользователю нужен очень специфический файл.Кроме того, относительные символические ссылки должны иметь одинаковое значение при перемещении в другое место в файловой системе - пользователь хотел, чтобы ссылки работали независимо от того, где находится дерево каталогов.

Но если два типа ссылок были смешанытогда вам нужно будет проделать еще кое-что - вот где, я полагаю, вы сейчас находитесь.(Unix-программы часто не так уж и просты, чтобы угадать намерения пользователя; если вы просто readlink(2) и symlink(2) в точности говорите о файловой системе, ваша программа никогда не будет удивительной .)

rsync(1) может иметь некоторый исходный код, который вы можете использовать - или, по крайней мере, учиться у него.Опция командной строки --safe-links заставляет rsync до игнорировать абсолютные символические ссылки и относительные символические ссылки, которые указывают вне деревьев, которым было поручено копировать.Это не канонизирует пути к относительному, как вы хотите, но может предоставить достаточный код для определения того, какие ссылки указывают вне рассматриваемого дерева каталогов.

Немного связано;специфичный для Linux системный вызов symlinkat(2) может упростить вам создание символических ссылок.(Семейство системных вызовов ...at() представляет собой нечто вроде обеспечения процесса несколькими «текущими рабочими каталогами», не заставляя вас делать все вызовы fchdir(2) самостоятельно.)

0 голосов
/ 12 марта 2012

Поначалу я не считал следующую информацию важной, но с помощью функции я нашел абсолютный путь к каталогам оригиналов и копий.

Таким образом, я наконец смог получить "относительный путь" к папке оригинала (путь, начинающийся с исходной папки), изменить корневой узел имени дерева каталога на скопированную папку, затем получить абсолютный путь к скопированной папке и добавить скопированную " относительный путь ", и все!

realpath(directory,absolutePath);

Вот как выглядит мой код:

readlink(A[i].str, oldLink, NAMESIZE);//A is the struct I keep the paths to directory entries
k=0;
j=strlen(absolutPath);
while(oldLink[j]!='\0')
{
    fixLink[k]=oldLink[j];
    j++;
    k++;
}
strcpy(tmpLink,newAbsolutPath);
strcat(tmpLink,fixLink);
symlink (tmpLink,tmpPath);//tmpPath is the name of the link, tmp link is the absolute path to the actual file
//tmpPath is built almost the same way

Пока он работает без ошибок

...