LINUX C如何将两个完整路径转换为相对路径(更新)

时间:2018-08-29 08:44:53

标签: c filepath

我想基于给定目录将完整路径转换为相对路径,

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$ 

0 个答案:

没有答案