我想基于给定目录将完整路径转换为相对路径,
realpath -m /home/mobile_c/relpath/CCR/Headers/gc.h --relative-to=/home/mobile_c/relpath/CCR/UserFiles/ccr_resources/Scripts/Garbage_Collector/gc.h
除了用C编码 但我不确定我会怎么做
我最初的预期结果是来自x文件,解析为x文件
因此它应该是,例如:
来自~/CCR/Headers/gc.h
到~/CCR/UserFiles/ccr_resources/Scripts/Garbage_Collector/gc.h
relative_path(从>到)= ../UserFiles/ccr_resources/Scripts/Garbage_Collector/gc.h
relative_path(至>从)= ../../../../Headers/gc.h
这是我目前拥有的
#define ps(x) printf("%s = %s\n", #x, x)
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <limits.h>
#include <libgen.h>
void pathCanonicalize (char *path)
{
size_t i;
size_t j;
size_t k;
//Move to the beginning of the string
i = 0;
k = 0;
//Replace backslashes with forward slashes
while (path[i] != '\0') {
//Forward slash or backslash separator found?
if (path[i] == '/' || path[i] == '\\') {
path[k++] = '/';
while (path[i] == '/' || path[i] == '\\')
i++;
} else {
path[k++] = path[i++];
}
}
//Properly terminate the string with a NULL character
path[k] = '\0';
//Move back to the beginning of the string
i = 0;
j = 0;
k = 0;
//Parse the entire string
do {
//Forward slash separator found?
if (path[i] == '/' || path[i] == '\0') {
//"." element found?
if ((i - j) == 1 && !strncmp (path + j, ".", 1)) {
//Check whether the pathname is empty?
if (k == 0) {
if (path[i] == '\0') {
path[k++] = '.';
} else if (path[i] == '/' && path[i + 1] == '\0') {
path[k++] = '.';
path[k++] = '/';
}
} else if (k > 1) {
//Remove the final slash if necessary
if (path[i] == '\0')
k--;
}
}
//".." element found?
else if ((i - j) == 2 && !strncmp (path + j, "..", 2)) {
//Check whether the pathname is empty?
if (k == 0) {
path[k++] = '.';
path[k++] = '.';
//Append a slash if necessary
if (path[i] == '/')
path[k++] = '/';
} else if (k > 1) {
//Search the path for the previous slash
for (j = 1; j < k; j++) {
if (path[k - j - 1] == '/')
break;
}
//Slash separator found?
if (j < k) {
if (!strncmp (path + k - j, "..", 2)) {
path[k++] = '.';
path[k++] = '.';
} else {
k = k - j - 1;
}
//Append a slash if necessary
if (k == 0 && path[0] == '/')
path[k++] = '/';
else if (path[i] == '/')
path[k++] = '/';
}
//No slash separator found?
else {
if (k == 3 && !strncmp (path, "..", 2)) {
path[k++] = '.';
path[k++] = '.';
//Append a slash if necessary
if (path[i] == '/')
path[k++] = '/';
} else if (path[i] == '\0') {
k = 0;
path[k++] = '.';
} else if (path[i] == '/' && path[i + 1] == '\0') {
k = 0;
path[k++] = '.';
path[k++] = '/';
} else {
k = 0;
}
}
}
} else {
//Copy directory name
memmove (path + k, path + j, i - j);
//Advance write pointer
k += i - j;
//Append a slash if necessary
if (path[i] == '/')
path[k++] = '/';
}
//Move to the next token
while (path[i] == '/')
i++;
j = i;
}
else if (k == 0) {
while (path[i] == '.' || path[i] == '/') {
j++,i++;
}
}
} while (path[i++] != '\0');
//Properly terminate the string with a NULL character
path[k] = '\0';
}
char * fullpath(char * path) {
char * buf = malloc(4096);
if (path[0] != '/') {
getcwd(buf, 4096);
strcat(buf, "/");
strcat(buf, path);
pathCanonicalize(buf);
return buf;
}
else {
strcpy(buf, path);
return buf;
}
}
char * resolve(char * from, char * to) {
printf("resolving from \"%s\" to \"%s\"\n", from, to);
puts("first, convert all paths to absolute paths");
from = fullpath(from);
to = fullpath(to);
ps(from);
ps(to);
puts("next, we attempt to convert to relative path");
free(from);
free(to);
return NULL;
}
int main ( int argc, char *argv[] )
{
char * to = "./CCR/Headers/gc.h";
char * from = "./CCR/UserFiles/ccr_resources/Scripts/Garbage_Collector/gc.h";
resolve(to,from);
resolve(from,to);
return 0;
}
和输出:
mobile_c@Mobile-C:~/relpath$ gcc ./rel.c && ./a.out
resolving from "./CCR/Headers/gc.h" to "./CCR/UserFiles/ccr_resources/Scripts/Garbage_Collector/gc.h"
first, convert all paths to absolute paths
from = /home/mobile_c/relpath/CCR/Headers/gc.h
to = /home/mobile_c/relpath/CCR/UserFiles/ccr_resources/Scripts/Garbage_Collector/gc.h
next, we attempt to convert to relative path
resolving from "./CCR/UserFiles/ccr_resources/Scripts/Garbage_Collector/gc.h" to "./CCR/Headers/gc.h"
first, convert all paths to absolute paths
from = /home/mobile_c/relpath/CCR/UserFiles/ccr_resources/Scripts/Garbage_Collector/gc.h
to = /home/mobile_c/relpath/CCR/Headers/gc.h
next, we attempt to convert to relative path
mobile_c@Mobile-C:~/relpath$