How to expand a path (Linux)

How can I expand a path like "~/MyDir"

Page 1 of 1

7 Replies - 5509 Views - Last Post: 05 November 2010 - 03:33 AM Rate Topic: -----

#1 Holi  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 4
  • Joined: 29-October 10

How to expand a path (Linux)

Posted 29 October 2010 - 06:28 AM

Hi there

I have an XML-file that I can parse and validate. Some of the attributes contain a path to a file which I read as std::string. This path has to be either absolute or relative - in both cases it works well (i.e. "../NextDirectory").

As the project is used amongst many users with different usernames, it is better to use something like "~/NextDirectory" or "${HOME}/NextDirectory" instead of "/home/anyuser/NextDirectory" or "../NextDirectory" (depends on the case, sometimes it's better to use absolute paths, but adaptive to usernames).

Is there a more or less easy way to get a path back as if a shell would resolve/expand it?

Thanks a lot

Is This A Good Question/Topic? 0
  • +

Replies To: How to expand a path (Linux)

#2 janotte  Icon User is offline

  • code > sword
  • member icon

Reputation: 990
  • View blog
  • Posts: 5,141
  • Joined: 28-September 06

Re: How to expand a path (Linux)

Posted 29 October 2010 - 06:41 AM

Things were going okay until this line.

Is there a more or less easy way to get a path back as if a shell would resolve/expand it?

What are you trying to say there?
Get the path back from where?

Are you trying to ask how you would parse a path from the XML into a generic path the the shell will recognise?
You seem to have already described how you could do that so that doesn't seem to be a logical question.

Sorry I really don't know what you are trying to ask us.
Was This Post Helpful? 0
  • +
  • -

#3 JackOfAllTrades  Icon User is offline

  • Saucy!
  • member icon

Reputation: 6033
  • View blog
  • Posts: 23,414
  • Joined: 23-August 08

Re: How to expand a path (Linux)

Posted 29 October 2010 - 07:04 AM

Sounds to me like the OP is looking for the Linux equivalent of the Win32 ExpandEnvironmentStrings function. I do not believe one exists, although I may be wrong.
Was This Post Helpful? 0
  • +
  • -

#4 Holi  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 4
  • Joined: 29-October 10

Re: How to expand a path (Linux)

Posted 29 October 2010 - 07:25 AM

What I'm looking for is something like this (assume the program runs from "/home/theUser/AnyPath"):
  std::string strPath = "~/MyPath";

  char* absolutePath = anySystemCallOrSoThatResolvesPath(strPath.c_str());
  /* -> absolutePath = "/home/theUser/MyPath" */
  free(absolutePath);
  absolutePath = NULL;

  strPath = "${HOME}/MyPath";
  absolutePath = anySystemCallOrSoThatResolvesPath(strPath.c_str());
  /* -> absolutePath = "/home/theUser/MyPath" */
  free(absolutePath);
  absolutePath = NULL;

  strPath = "$HOME/MyPath";
  absolutePath = anySystemCallOrSoThatResolvesPath(strPath.c_str());
  /* -> absolutePath = "/home/theUser/MyPath" */
  free(absolutePath);
  absolutePath = NULL;

  strPath = "../MyPath";
  absolutePath = anySystemCallOrSoThatResolvesPath(strPath.c_str());
  /* -> absolutePath = "/home/theUser/MyPath" */
  free(absolutePath);
  absolutePath = NULL;

  strPath = "${ANY_OTHER_PATH}/../MyPath";
  absolutePath = anySystemCallOrSoThatResolvesPath(strPath.c_str());
  /* -> absolutePath = "/home/theUser/MyPath" */
  free(absolutePath);
  absolutePath = NULL;



But I don't want to do the whole parsing logic if possible, as I believe there must be some sort of library that already provides this functionality.

This post has been edited by Holi: 29 October 2010 - 07:35 AM

Was This Post Helpful? 0
  • +
  • -

#5 JackOfAllTrades  Icon User is offline

  • Saucy!
  • member icon

Reputation: 6033
  • View blog
  • Posts: 23,414
  • Joined: 23-August 08

Re: How to expand a path (Linux)

Posted 29 October 2010 - 07:38 AM

Google searches point to the publib library, like here.
Was This Post Helpful? 1
  • +
  • -

#6 Holi  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 4
  • Joined: 29-October 10

Re: How to expand a path (Linux)

Posted 04 November 2010 - 01:30 AM

Thanks, the publib probably is the way to go although I have a lot of build-errors with it at the first glance (hopefully nothing I'm not able to solve :bigsmile: ).
Was This Post Helpful? 0
  • +
  • -

#7 baavgai  Icon User is offline

  • Dreaming Coder
  • member icon

Reputation: 5761
  • View blog
  • Posts: 12,574
  • Joined: 16-October 07

Re: How to expand a path (Linux)

Posted 04 November 2010 - 11:25 AM

This nagged the hell out of me. There should be a simple way to do this, you'd think. Particularly environment variable resolution.

I ultimately found a GNU function, wordexp, which will figure out those variables. One of the most poorly documented things I've seen, but it works.

There is another function called realpath. That should play nice, but it really wants the path to exist, which is kind of annoying.

I ended up with something manual but not too long. If you can figure out a way to trick it, let me know.

#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
#include <wordexp.h>
#include <string.h>

char *abspath(const char *file_name, char *resolved_name);

void testPath(const char *path) {
	char buff[PATH_MAX+1];
	printf("'%s' -> '%s'\n", path, abspath(path, buff));
}


int main() {
	testPath(".");
	testPath("..");
	testPath("abspath/");
	testPath("oops/");
	testPath("~/MyPath");
	testPath("${HOME}/./MyPath");
	testPath("${HOME}/./foo");
	testPath("${HOME}/.//foo");
	testPath("$HOME/MyPath");
	testPath("../MyPath");
	testPath("foo/bar/../MyPath");
	return 0;
}


static void appendCwd(const char *path, char *dst) {
	if (path[0]=='/') {
		strcpy(dst, path);
	} else {
		getcwd(dst, PATH_MAX);
		strcat(dst, "/");
		strcat(dst, path);
	}
}

static void removeJunk(char *begin, char *end) {
	while(*end!=0) { *begin++ = *end++; }
	*begin = 0;
}

static char *manualPathFold(char *path) {
	char *s, *priorSlash;
	while ((s=strstr(path, "/../"))!=NULL) {
		*s = 0;
		if ((priorSlash = strrchr(path, '/'))==NULL) { /* oops */ *s = '/'; break; }
		removeJunk(priorSlash, s+3);
	}
	while ((s=strstr(path, "/./"))!=NULL) { removeJunk(s, s+2); }
	while ((s=strstr(path, "//"))!=NULL) { removeJunk(s, s+1); }
	s = path + (strlen(path)-1);
	if (s!=path && *s=='/') { *s=0; }
	return path;
}


char *abspath(const char *file_name, char *resolved_name) {
	char buff[PATH_MAX+1];
	wordexp_t p;
	if (wordexp(file_name, &p, 0)==0) {
		appendCwd(p.we_wordv[0], buff);
		wordfree(&p);
	} else { 
		appendCwd(file_name, buff);
	}
	if (realpath(buff, resolved_name)==NULL) { strcpy(resolved_name, manualPathFold(buff)); }
	return resolved_name;
}


Was This Post Helpful? 2
  • +
  • -

#8 Holi  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 4
  • Joined: 29-October 10

Re: How to expand a path (Linux)

Posted 05 November 2010 - 03:33 AM

Fabulous!!! Thanks a lot :bananaman:
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1